nv_video.c revision 6086d97e
1fc5a983dSmrg#ifdef HAVE_CONFIG_H 2fc5a983dSmrg#include "config.h" 3fc5a983dSmrg#endif 4fc5a983dSmrg 5fc5a983dSmrg#include "xf86.h" 6fc5a983dSmrg#include "xf86_OSproc.h" 7fc5a983dSmrg#include "compiler.h" 8fc5a983dSmrg#include "xf86PciInfo.h" 9fc5a983dSmrg#include "xf86Pci.h" 10fc5a983dSmrg#include "xf86fbman.h" 11fc5a983dSmrg#include "regionstr.h" 12fc5a983dSmrg 13fc5a983dSmrg#include "xf86xv.h" 14fc5a983dSmrg#include <X11/extensions/Xv.h> 15fc5a983dSmrg#include "xaa.h" 16fc5a983dSmrg#include "xaalocal.h" 17fc5a983dSmrg#include "dixstruct.h" 18fc5a983dSmrg#include "fourcc.h" 19fc5a983dSmrg 20fc5a983dSmrg#include "nv_include.h" 21fc5a983dSmrg#include "nv_dma.h" 22fc5a983dSmrg 23fc5a983dSmrg#define OFF_DELAY 500 /* milliseconds */ 24fc5a983dSmrg#define FREE_DELAY 5000 25fc5a983dSmrg 26fc5a983dSmrg#define OFF_TIMER 0x01 27fc5a983dSmrg#define FREE_TIMER 0x02 28fc5a983dSmrg#define CLIENT_VIDEO_ON 0x04 29fc5a983dSmrg 30fc5a983dSmrg#define TIMER_MASK (OFF_TIMER | FREE_TIMER) 31fc5a983dSmrg 32fc5a983dSmrg#define NUM_BLIT_PORTS 32 33fc5a983dSmrg 34fc5a983dSmrgtypedef struct _NVPortPrivRec { 35fc5a983dSmrg short brightness; 36fc5a983dSmrg short contrast; 37fc5a983dSmrg short saturation; 38fc5a983dSmrg short hue; 39fc5a983dSmrg RegionRec clip; 40fc5a983dSmrg CARD32 colorKey; 41fc5a983dSmrg Bool autopaintColorKey; 42fc5a983dSmrg Bool doubleBuffer; 43fc5a983dSmrg CARD32 videoStatus; 44fc5a983dSmrg int currentBuffer; 45fc5a983dSmrg Time videoTime; 46fc5a983dSmrg Bool grabbedByV4L; 47fc5a983dSmrg Bool iturbt_709; 48fc5a983dSmrg Bool blitter; 49fc5a983dSmrg Bool SyncToVBlank; 50fc5a983dSmrg FBLinearPtr linear; 51fc5a983dSmrg int pitch; 52fc5a983dSmrg int offset; 53fc5a983dSmrg} NVPortPrivRec, *NVPortPrivPtr; 54fc5a983dSmrg 55fc5a983dSmrg 56fc5a983dSmrgstatic XF86VideoAdaptorPtr NVSetupOverlayVideo(ScreenPtr); 57fc5a983dSmrgstatic XF86VideoAdaptorPtr NVSetupBlitVideo(ScreenPtr); 58fc5a983dSmrg 59fc5a983dSmrgstatic void NVStopOverlay (ScrnInfoPtr); 60fc5a983dSmrgstatic void NVPutOverlayImage(ScrnInfoPtr pScrnInfo, 61fc5a983dSmrg int offset, 62fc5a983dSmrg int id, 63fc5a983dSmrg int dstPitch, 64fc5a983dSmrg BoxPtr dstBox, 65fc5a983dSmrg int x1, int y1, int x2, int y2, 66fc5a983dSmrg short width, short height, 67fc5a983dSmrg short src_w, short src_h, 68fc5a983dSmrg short dst_w, short dst_h, 69fc5a983dSmrg RegionPtr cliplist); 70fc5a983dSmrg 71fc5a983dSmrgstatic int NVSetOverlayPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); 72fc5a983dSmrgstatic int NVGetOverlayPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); 73fc5a983dSmrgstatic int NVSetBlitPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); 74fc5a983dSmrgstatic int NVGetBlitPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); 75fc5a983dSmrg 76fc5a983dSmrg 77fc5a983dSmrgstatic void NVStopOverlayVideo(ScrnInfoPtr, pointer, Bool); 78fc5a983dSmrgstatic void NVStopBlitVideo(ScrnInfoPtr, pointer, Bool); 79fc5a983dSmrg 80fc5a983dSmrgstatic int NVPutImage( ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer, DrawablePtr); 81fc5a983dSmrg 82fc5a983dSmrgstatic void NVQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short, unsigned int *, unsigned int *, pointer); 83fc5a983dSmrgstatic int NVQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, unsigned short *, int *, int *); 84fc5a983dSmrg 85fc5a983dSmrgstatic void NVVideoTimerCallback(ScrnInfoPtr, Time); 86fc5a983dSmrg 87fc5a983dSmrgstatic void NVInitOffscreenImages (ScreenPtr pScreen); 88fc5a983dSmrg 89fc5a983dSmrg 90fc5a983dSmrg#define GET_OVERLAY_PRIVATE(pNv) \ 91fc5a983dSmrg (NVPortPrivPtr)((pNv)->overlayAdaptor->pPortPrivates[0].ptr) 92fc5a983dSmrg 93fc5a983dSmrg#define GET_BLIT_PRIVATE(pNv) \ 94fc5a983dSmrg (NVPortPrivPtr)((pNv)->blitAdaptor->pPortPrivates[0].ptr) 95fc5a983dSmrg 96fc5a983dSmrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 97fc5a983dSmrg 98fc5a983dSmrgstatic Atom xvBrightness, xvContrast, xvColorKey, xvSaturation, 99fc5a983dSmrg xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer, 100fc5a983dSmrg xvITURBT709, xvSyncToVBlank; 101fc5a983dSmrg 102fc5a983dSmrg/* client libraries expect an encoding */ 103fc5a983dSmrgstatic XF86VideoEncodingRec DummyEncoding = 104fc5a983dSmrg{ 105fc5a983dSmrg 0, 106fc5a983dSmrg "XV_IMAGE", 107fc5a983dSmrg 2046, 2046, 108fc5a983dSmrg {1, 1} 109fc5a983dSmrg}; 110fc5a983dSmrg 111fc5a983dSmrg#define NUM_FORMATS_ALL 6 112fc5a983dSmrg 113fc5a983dSmrgXF86VideoFormatRec NVFormats[NUM_FORMATS_ALL] = 114fc5a983dSmrg{ 115fc5a983dSmrg {15, TrueColor}, {16, TrueColor}, {24, TrueColor}, 116fc5a983dSmrg {15, DirectColor}, {16, DirectColor}, {24, DirectColor} 117fc5a983dSmrg}; 118fc5a983dSmrg 119fc5a983dSmrg#define NUM_OVERLAY_ATTRIBUTES 9 120fc5a983dSmrgXF86AttributeRec NVOverlayAttributes[NUM_OVERLAY_ATTRIBUTES] = 121fc5a983dSmrg{ 122fc5a983dSmrg {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"}, 123fc5a983dSmrg {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 124fc5a983dSmrg {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"}, 125fc5a983dSmrg {XvSettable , 0, 0, "XV_SET_DEFAULTS"}, 126fc5a983dSmrg {XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"}, 127fc5a983dSmrg {XvSettable | XvGettable, 0, 8191, "XV_CONTRAST"}, 128fc5a983dSmrg {XvSettable | XvGettable, 0, 8191, "XV_SATURATION"}, 129fc5a983dSmrg {XvSettable | XvGettable, 0, 360, "XV_HUE"}, 130fc5a983dSmrg {XvSettable | XvGettable, 0, 1, "XV_ITURBT_709"} 131fc5a983dSmrg}; 132fc5a983dSmrg 133fc5a983dSmrg#define NUM_BLIT_ATTRIBUTES 2 134fc5a983dSmrgXF86AttributeRec NVBlitAttributes[NUM_BLIT_ATTRIBUTES] = 135fc5a983dSmrg{ 136fc5a983dSmrg {XvSettable , 0, 0, "XV_SET_DEFAULTS"}, 137fc5a983dSmrg {XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"} 138fc5a983dSmrg}; 139fc5a983dSmrg 140fc5a983dSmrg 141fc5a983dSmrg#define NUM_IMAGES_YUV 4 142fc5a983dSmrg#define NUM_IMAGES_ALL 5 143fc5a983dSmrg 144fc5a983dSmrg#define FOURCC_RGB 0x0000003 145fc5a983dSmrg#define XVIMAGE_RGB \ 146fc5a983dSmrg { \ 147fc5a983dSmrg FOURCC_RGB, \ 148fc5a983dSmrg XvRGB, \ 149fc5a983dSmrg LSBFirst, \ 150fc5a983dSmrg { 0x03, 0x00, 0x00, 0x00, \ 151fc5a983dSmrg 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ 152fc5a983dSmrg 32, \ 153fc5a983dSmrg XvPacked, \ 154fc5a983dSmrg 1, \ 155fc5a983dSmrg 24, 0x00ff0000, 0x0000ff00, 0x000000ff, \ 156fc5a983dSmrg 0, 0, 0, \ 157fc5a983dSmrg 0, 0, 0, \ 158fc5a983dSmrg 0, 0, 0, \ 159fc5a983dSmrg {'B','G','R','X',\ 160fc5a983dSmrg 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}, \ 161fc5a983dSmrg XvTopToBottom \ 162fc5a983dSmrg } 163fc5a983dSmrg 164fc5a983dSmrgstatic XF86ImageRec NVImages[NUM_IMAGES_ALL] = 165fc5a983dSmrg{ 166fc5a983dSmrg XVIMAGE_YUY2, 167fc5a983dSmrg XVIMAGE_YV12, 168fc5a983dSmrg XVIMAGE_UYVY, 169fc5a983dSmrg XVIMAGE_I420, 170fc5a983dSmrg XVIMAGE_RGB 171fc5a983dSmrg}; 172fc5a983dSmrg 173fc5a983dSmrgstatic void 174fc5a983dSmrgNVSetPortDefaults (ScrnInfoPtr pScrnInfo, NVPortPrivPtr pPriv) 175fc5a983dSmrg{ 176fc5a983dSmrg NVPtr pNv = NVPTR(pScrnInfo); 177fc5a983dSmrg 178fc5a983dSmrg pPriv->brightness = 0; 179fc5a983dSmrg pPriv->contrast = 4096; 180fc5a983dSmrg pPriv->saturation = 4096; 181fc5a983dSmrg pPriv->hue = 0; 182fc5a983dSmrg pPriv->colorKey = pNv->videoKey; 183fc5a983dSmrg pPriv->autopaintColorKey = TRUE; 184fc5a983dSmrg pPriv->doubleBuffer = TRUE; 185fc5a983dSmrg pPriv->iturbt_709 = FALSE; 186fc5a983dSmrg} 187fc5a983dSmrg 188fc5a983dSmrg 189fc5a983dSmrgvoid 190fc5a983dSmrgNVResetVideo (ScrnInfoPtr pScrnInfo) 191fc5a983dSmrg{ 192fc5a983dSmrg NVPtr pNv = NVPTR(pScrnInfo); 193fc5a983dSmrg NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); 194fc5a983dSmrg int satSine, satCosine; 195fc5a983dSmrg double angle; 196fc5a983dSmrg 197fc5a983dSmrg angle = (double)pPriv->hue * 3.1415927 / 180.0; 198fc5a983dSmrg 199fc5a983dSmrg satSine = pPriv->saturation * sin(angle); 200fc5a983dSmrg if (satSine < -1024) 201fc5a983dSmrg satSine = -1024; 202fc5a983dSmrg satCosine = pPriv->saturation * cos(angle); 203fc5a983dSmrg if (satCosine < -1024) 204fc5a983dSmrg satCosine = -1024; 205fc5a983dSmrg 206fc5a983dSmrg pNv->PMC[0x8910/4] = (pPriv->brightness << 16) | pPriv->contrast; 207fc5a983dSmrg pNv->PMC[0x8914/4] = (pPriv->brightness << 16) | pPriv->contrast; 208fc5a983dSmrg pNv->PMC[0x8918/4] = (satSine << 16) | (satCosine & 0xffff); 209fc5a983dSmrg pNv->PMC[0x891C/4] = (satSine << 16) | (satCosine & 0xffff); 210fc5a983dSmrg pNv->PMC[0x8b00/4] = pPriv->colorKey; 211fc5a983dSmrg} 212fc5a983dSmrg 213fc5a983dSmrg 214fc5a983dSmrg 215fc5a983dSmrgstatic void 216fc5a983dSmrgNVStopOverlay (ScrnInfoPtr pScrnInfo) 217fc5a983dSmrg{ 218fc5a983dSmrg NVPtr pNv = NVPTR(pScrnInfo); 219fc5a983dSmrg 220fc5a983dSmrg pNv->PMC[0x00008704/4] = 1; 221fc5a983dSmrg} 222fc5a983dSmrg 223fc5a983dSmrgstatic FBLinearPtr 224fc5a983dSmrgNVAllocateOverlayMemory( 225fc5a983dSmrg ScrnInfoPtr pScrn, 226fc5a983dSmrg FBLinearPtr linear, 227fc5a983dSmrg int size 228fc5a983dSmrg){ 229fc5a983dSmrg ScreenPtr pScreen; 230fc5a983dSmrg FBLinearPtr new_linear; 231fc5a983dSmrg 232fc5a983dSmrg if(linear) { 233fc5a983dSmrg if(linear->size >= size) 234fc5a983dSmrg return linear; 235fc5a983dSmrg 236fc5a983dSmrg if(xf86ResizeOffscreenLinear(linear, size)) 237fc5a983dSmrg return linear; 238fc5a983dSmrg 239fc5a983dSmrg xf86FreeOffscreenLinear(linear); 240fc5a983dSmrg } 241fc5a983dSmrg 242fc5a983dSmrg pScreen = screenInfo.screens[pScrn->scrnIndex]; 243fc5a983dSmrg 244fc5a983dSmrg new_linear = xf86AllocateOffscreenLinear(pScreen, size, 32, 245fc5a983dSmrg NULL, NULL, NULL); 246fc5a983dSmrg 247fc5a983dSmrg if(!new_linear) { 248fc5a983dSmrg int max_size; 249fc5a983dSmrg 250fc5a983dSmrg xf86QueryLargestOffscreenLinear(pScreen, &max_size, 32, 251fc5a983dSmrg PRIORITY_EXTREME); 252fc5a983dSmrg 253fc5a983dSmrg if(max_size < size) 254fc5a983dSmrg return NULL; 255fc5a983dSmrg 256fc5a983dSmrg xf86PurgeUnlockedOffscreenAreas(pScreen); 257fc5a983dSmrg new_linear = xf86AllocateOffscreenLinear(pScreen, size, 32, 258fc5a983dSmrg NULL, NULL, NULL); 259fc5a983dSmrg } 260fc5a983dSmrg 261fc5a983dSmrg return new_linear; 262fc5a983dSmrg} 263fc5a983dSmrg 264fc5a983dSmrgstatic void NVFreeOverlayMemory(ScrnInfoPtr pScrnInfo) 265fc5a983dSmrg{ 266fc5a983dSmrg NVPtr pNv = NVPTR(pScrnInfo); 267fc5a983dSmrg NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); 268fc5a983dSmrg 269fc5a983dSmrg if(pPriv->linear) { 270fc5a983dSmrg xf86FreeOffscreenLinear(pPriv->linear); 271fc5a983dSmrg pPriv->linear = NULL; 272fc5a983dSmrg } 273fc5a983dSmrg} 274fc5a983dSmrg 275fc5a983dSmrg 276fc5a983dSmrgstatic void NVFreeBlitMemory(ScrnInfoPtr pScrnInfo) 277fc5a983dSmrg{ 278fc5a983dSmrg NVPtr pNv = NVPTR(pScrnInfo); 279fc5a983dSmrg NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv); 280fc5a983dSmrg 281fc5a983dSmrg if(pPriv->linear) { 282fc5a983dSmrg xf86FreeOffscreenLinear(pPriv->linear); 283fc5a983dSmrg pPriv->linear = NULL; 284fc5a983dSmrg } 285fc5a983dSmrg} 286fc5a983dSmrg 287fc5a983dSmrg 288fc5a983dSmrgvoid NVInitVideo (ScreenPtr pScreen) 289fc5a983dSmrg{ 290fc5a983dSmrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 291fc5a983dSmrg XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; 292fc5a983dSmrg XF86VideoAdaptorPtr overlayAdaptor = NULL; 293fc5a983dSmrg XF86VideoAdaptorPtr blitAdaptor = NULL; 294fc5a983dSmrg NVPtr pNv = NVPTR(pScrn); 295fc5a983dSmrg int num_adaptors; 296fc5a983dSmrg 297fc5a983dSmrg if((pScrn->bitsPerPixel != 8) && (pNv->Architecture >= NV_ARCH_10) && 298fc5a983dSmrg ((pNv->Architecture <= NV_ARCH_30) || 299fc5a983dSmrg ((pNv->Chipset & 0xfff0) == 0x0040))) 300fc5a983dSmrg { 301fc5a983dSmrg overlayAdaptor = NVSetupOverlayVideo(pScreen); 302fc5a983dSmrg 303fc5a983dSmrg if(overlayAdaptor) 304fc5a983dSmrg NVInitOffscreenImages(pScreen); 305fc5a983dSmrg } 306fc5a983dSmrg 307fc5a983dSmrg if((pScrn->bitsPerPixel != 8) && !pNv->NoAccel) 308fc5a983dSmrg blitAdaptor = NVSetupBlitVideo(pScreen); 309fc5a983dSmrg 310fc5a983dSmrg num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 311fc5a983dSmrg 312fc5a983dSmrg if(blitAdaptor || overlayAdaptor) { 313fc5a983dSmrg int size = num_adaptors; 314fc5a983dSmrg 315fc5a983dSmrg if(overlayAdaptor) size++; 316fc5a983dSmrg if(blitAdaptor) size++; 317fc5a983dSmrg 3186086d97eSmrg if((newAdaptors = malloc(size * sizeof(XF86VideoAdaptorPtr*)))) { 319fc5a983dSmrg if(num_adaptors) { 320fc5a983dSmrg memcpy(newAdaptors, adaptors, 321fc5a983dSmrg num_adaptors * sizeof(XF86VideoAdaptorPtr)); 322fc5a983dSmrg } 323fc5a983dSmrg if(overlayAdaptor) { 324fc5a983dSmrg newAdaptors[num_adaptors] = overlayAdaptor; 325fc5a983dSmrg num_adaptors++; 326fc5a983dSmrg } 327fc5a983dSmrg if(blitAdaptor) { 328fc5a983dSmrg newAdaptors[num_adaptors] = blitAdaptor; 329fc5a983dSmrg num_adaptors++; 330fc5a983dSmrg } 331fc5a983dSmrg adaptors = newAdaptors; 332fc5a983dSmrg } 333fc5a983dSmrg } 334fc5a983dSmrg 335fc5a983dSmrg if (num_adaptors) 336fc5a983dSmrg xf86XVScreenInit(pScreen, adaptors, num_adaptors); 337fc5a983dSmrg 338fc5a983dSmrg if (newAdaptors) 3396086d97eSmrg free(newAdaptors); 340fc5a983dSmrg} 341fc5a983dSmrg 342fc5a983dSmrg 343fc5a983dSmrgstatic XF86VideoAdaptorPtr 344fc5a983dSmrgNVSetupBlitVideo (ScreenPtr pScreen) 345fc5a983dSmrg{ 346fc5a983dSmrg ScrnInfoPtr pScrnInfo = xf86Screens[pScreen->myNum]; 347fc5a983dSmrg NVPtr pNv = NVPTR(pScrnInfo); 348fc5a983dSmrg XF86VideoAdaptorPtr adapt; 349fc5a983dSmrg NVPortPrivPtr pPriv; 350fc5a983dSmrg int i; 351fc5a983dSmrg 3526086d97eSmrg if (!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + 353fc5a983dSmrg sizeof(NVPortPrivRec) + 354fc5a983dSmrg (sizeof(DevUnion) * NUM_BLIT_PORTS)))) 355fc5a983dSmrg { 356fc5a983dSmrg return NULL; 357fc5a983dSmrg } 358fc5a983dSmrg 359fc5a983dSmrg adapt->type = XvWindowMask | XvInputMask | XvImageMask; 360fc5a983dSmrg adapt->flags = 0; 361fc5a983dSmrg adapt->name = "NV Video Blitter"; 362fc5a983dSmrg adapt->nEncodings = 1; 363fc5a983dSmrg adapt->pEncodings = &DummyEncoding; 364fc5a983dSmrg adapt->nFormats = NUM_FORMATS_ALL; 365fc5a983dSmrg adapt->pFormats = NVFormats; 366fc5a983dSmrg adapt->nPorts = NUM_BLIT_PORTS; 367fc5a983dSmrg adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 368fc5a983dSmrg 369fc5a983dSmrg pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_BLIT_PORTS]); 370fc5a983dSmrg for(i = 0; i < NUM_BLIT_PORTS; i++) 371fc5a983dSmrg adapt->pPortPrivates[i].ptr = (pointer)(pPriv); 372fc5a983dSmrg 373fc5a983dSmrg if(pNv->WaitVSyncPossible) { 374fc5a983dSmrg adapt->pAttributes = NVBlitAttributes; 375fc5a983dSmrg adapt->nAttributes = NUM_BLIT_ATTRIBUTES; 376fc5a983dSmrg } else { 377fc5a983dSmrg adapt->pAttributes = NULL; 378fc5a983dSmrg adapt->nAttributes = 0; 379fc5a983dSmrg } 380fc5a983dSmrg adapt->pImages = NVImages; 381fc5a983dSmrg adapt->nImages = NUM_IMAGES_ALL; 382fc5a983dSmrg adapt->PutVideo = NULL; 383fc5a983dSmrg adapt->PutStill = NULL; 384fc5a983dSmrg adapt->GetVideo = NULL; 385fc5a983dSmrg adapt->GetStill = NULL; 386fc5a983dSmrg adapt->StopVideo = NVStopBlitVideo; 387fc5a983dSmrg adapt->SetPortAttribute = NVSetBlitPortAttribute; 388fc5a983dSmrg adapt->GetPortAttribute = NVGetBlitPortAttribute; 389fc5a983dSmrg adapt->QueryBestSize = NVQueryBestSize; 390fc5a983dSmrg adapt->PutImage = NVPutImage; 391fc5a983dSmrg adapt->QueryImageAttributes = NVQueryImageAttributes; 392fc5a983dSmrg 393fc5a983dSmrg pPriv->videoStatus = 0; 394fc5a983dSmrg pPriv->grabbedByV4L = FALSE; 395fc5a983dSmrg pPriv->blitter = TRUE; 396fc5a983dSmrg pPriv->doubleBuffer = FALSE; 397fc5a983dSmrg pPriv->SyncToVBlank = pNv->WaitVSyncPossible; 398fc5a983dSmrg 399fc5a983dSmrg pNv->blitAdaptor = adapt; 400fc5a983dSmrg 401fc5a983dSmrg xvSyncToVBlank = MAKE_ATOM("XV_SYNC_TO_VBLANK"); 402fc5a983dSmrg 403fc5a983dSmrg return adapt; 404fc5a983dSmrg} 405fc5a983dSmrg 406fc5a983dSmrgstatic XF86VideoAdaptorPtr 407fc5a983dSmrgNVSetupOverlayVideo (ScreenPtr pScreen) 408fc5a983dSmrg{ 409fc5a983dSmrg ScrnInfoPtr pScrnInfo = xf86Screens[pScreen->myNum]; 410fc5a983dSmrg NVPtr pNv = NVPTR(pScrnInfo); 411fc5a983dSmrg XF86VideoAdaptorPtr adapt; 412fc5a983dSmrg NVPortPrivPtr pPriv; 413fc5a983dSmrg 4146086d97eSmrg if (!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + 415fc5a983dSmrg sizeof(NVPortPrivRec) + 416fc5a983dSmrg sizeof(DevUnion)))) 417fc5a983dSmrg { 418fc5a983dSmrg return NULL; 419fc5a983dSmrg } 420fc5a983dSmrg 421fc5a983dSmrg adapt->type = XvWindowMask | XvInputMask | XvImageMask; 422fc5a983dSmrg adapt->flags = VIDEO_OVERLAID_IMAGES|VIDEO_CLIP_TO_VIEWPORT; 423fc5a983dSmrg adapt->name = "NV Video Overlay"; 424fc5a983dSmrg adapt->nEncodings = 1; 425fc5a983dSmrg adapt->pEncodings = &DummyEncoding; 426fc5a983dSmrg adapt->nFormats = NUM_FORMATS_ALL; 427fc5a983dSmrg adapt->pFormats = NVFormats; 428fc5a983dSmrg adapt->nPorts = 1; 429fc5a983dSmrg adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 430fc5a983dSmrg pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[1]); 431fc5a983dSmrg adapt->pPortPrivates[0].ptr = (pointer)(pPriv); 432fc5a983dSmrg adapt->pAttributes = NVOverlayAttributes; 433fc5a983dSmrg adapt->nAttributes = NUM_OVERLAY_ATTRIBUTES; 434fc5a983dSmrg adapt->pImages = NVImages; 435fc5a983dSmrg adapt->nImages = NUM_IMAGES_YUV; 436fc5a983dSmrg adapt->PutVideo = NULL; 437fc5a983dSmrg adapt->PutStill = NULL; 438fc5a983dSmrg adapt->GetVideo = NULL; 439fc5a983dSmrg adapt->GetStill = NULL; 440fc5a983dSmrg adapt->StopVideo = NVStopOverlayVideo; 441fc5a983dSmrg adapt->SetPortAttribute = NVSetOverlayPortAttribute; 442fc5a983dSmrg adapt->GetPortAttribute = NVGetOverlayPortAttribute; 443fc5a983dSmrg adapt->QueryBestSize = NVQueryBestSize; 444fc5a983dSmrg adapt->PutImage = NVPutImage; 445fc5a983dSmrg adapt->QueryImageAttributes = NVQueryImageAttributes; 446fc5a983dSmrg 447fc5a983dSmrg pPriv->videoStatus = 0; 448fc5a983dSmrg pPriv->currentBuffer = 0; 449fc5a983dSmrg pPriv->grabbedByV4L = FALSE; 450fc5a983dSmrg pPriv->blitter = FALSE; 451fc5a983dSmrg 452fc5a983dSmrg NVSetPortDefaults (pScrnInfo, pPriv); 453fc5a983dSmrg 454fc5a983dSmrg /* gotta uninit this someplace */ 455fc5a983dSmrg REGION_NULL(pScreen, &pPriv->clip); 456fc5a983dSmrg 457fc5a983dSmrg pNv->overlayAdaptor = adapt; 458fc5a983dSmrg 459fc5a983dSmrg xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 460fc5a983dSmrg xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER"); 461fc5a983dSmrg xvContrast = MAKE_ATOM("XV_CONTRAST"); 462fc5a983dSmrg xvColorKey = MAKE_ATOM("XV_COLORKEY"); 463fc5a983dSmrg xvSaturation = MAKE_ATOM("XV_SATURATION"); 464fc5a983dSmrg xvHue = MAKE_ATOM("XV_HUE"); 465fc5a983dSmrg xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); 466fc5a983dSmrg xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS"); 467fc5a983dSmrg xvITURBT709 = MAKE_ATOM("XV_ITURBT_709"); 468fc5a983dSmrg 469fc5a983dSmrg NVResetVideo(pScrnInfo); 470fc5a983dSmrg 471fc5a983dSmrg return adapt; 472fc5a983dSmrg} 473fc5a983dSmrg 474fc5a983dSmrgstatic void 475fc5a983dSmrgNVPutOverlayImage ( 476fc5a983dSmrg ScrnInfoPtr pScrnInfo, 477fc5a983dSmrg int offset, 478fc5a983dSmrg int id, 479fc5a983dSmrg int dstPitch, 480fc5a983dSmrg BoxPtr dstBox, 481fc5a983dSmrg int x1, 482fc5a983dSmrg int y1, 483fc5a983dSmrg int x2, 484fc5a983dSmrg int y2, 485fc5a983dSmrg short width, 486fc5a983dSmrg short height, 487fc5a983dSmrg short src_w, 488fc5a983dSmrg short src_h, 489fc5a983dSmrg short drw_w, 490fc5a983dSmrg short drw_h, 491fc5a983dSmrg RegionPtr clipBoxes 492fc5a983dSmrg) 493fc5a983dSmrg{ 494fc5a983dSmrg NVPtr pNv = NVPTR(pScrnInfo); 495fc5a983dSmrg NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); 496fc5a983dSmrg int buffer = pPriv->currentBuffer; 497fc5a983dSmrg 498fc5a983dSmrg /* paint the color key */ 499fc5a983dSmrg if(pPriv->autopaintColorKey && 500fc5a983dSmrg (pPriv->grabbedByV4L || 501fc5a983dSmrg !REGION_EQUAL(pScrnInfo->pScreen, &pPriv->clip, clipBoxes))) 502fc5a983dSmrg { 503fc5a983dSmrg /* we always paint V4L's color key */ 504fc5a983dSmrg if(!pPriv->grabbedByV4L) 505fc5a983dSmrg REGION_COPY(pScrnInfo->pScreen, &pPriv->clip, clipBoxes); 506fc5a983dSmrg xf86XVFillKeyHelper(pScrnInfo->pScreen, pPriv->colorKey, clipBoxes); 507fc5a983dSmrg } 508fc5a983dSmrg 509fc5a983dSmrg if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) { 510fc5a983dSmrg dstBox->y1 <<= 1; 511fc5a983dSmrg dstBox->y2 <<= 1; 512fc5a983dSmrg drw_h <<= 1; 513fc5a983dSmrg } 514fc5a983dSmrg 515fc5a983dSmrg pNv->PMC[(0x8900/4) + buffer] = offset; 516fc5a983dSmrg pNv->PMC[(0x8928/4) + buffer] = (height << 16) | width; 517fc5a983dSmrg pNv->PMC[(0x8930/4) + buffer] = ((y1 << 4) & 0xffff0000) | (x1 >> 12); 518fc5a983dSmrg pNv->PMC[(0x8938/4) + buffer] = (src_w << 20) / drw_w; 519fc5a983dSmrg pNv->PMC[(0x8940/4) + buffer] = (src_h << 20) / drw_h; 520fc5a983dSmrg pNv->PMC[(0x8948/4) + buffer] = (dstBox->y1 << 16) | dstBox->x1; 521fc5a983dSmrg pNv->PMC[(0x8950/4) + buffer] = ((dstBox->y2 - dstBox->y1) << 16) | 522fc5a983dSmrg (dstBox->x2 - dstBox->x1); 523fc5a983dSmrg 524fc5a983dSmrg dstPitch |= 1 << 20; /* use color key */ 525fc5a983dSmrg 526fc5a983dSmrg if(id != FOURCC_UYVY) 527fc5a983dSmrg dstPitch |= 1 << 16; 528fc5a983dSmrg if(pPriv->iturbt_709) 529fc5a983dSmrg dstPitch |= 1 << 24; 530fc5a983dSmrg 531fc5a983dSmrg pNv->PMC[(0x8958/4) + buffer] = dstPitch; 532fc5a983dSmrg pNv->PMC[0x00008704/4] = 0; 533fc5a983dSmrg pNv->PMC[0x8700/4] = 1 << (buffer << 2); 534fc5a983dSmrg 535fc5a983dSmrg pPriv->videoStatus = CLIENT_VIDEO_ON; 536fc5a983dSmrg} 537fc5a983dSmrg 538fc5a983dSmrg 539fc5a983dSmrg 540fc5a983dSmrgstatic void 541fc5a983dSmrgNVPutBlitImage ( 542fc5a983dSmrg ScrnInfoPtr pScrnInfo, 543fc5a983dSmrg int offset, 544fc5a983dSmrg int id, 545fc5a983dSmrg int dstPitch, 546fc5a983dSmrg BoxPtr dstBox, 547fc5a983dSmrg int x1, 548fc5a983dSmrg int y1, 549fc5a983dSmrg int x2, 550fc5a983dSmrg int y2, 551fc5a983dSmrg short width, 552fc5a983dSmrg short height, 553fc5a983dSmrg short src_w, 554fc5a983dSmrg short src_h, 555fc5a983dSmrg short drw_w, 556fc5a983dSmrg short drw_h, 557fc5a983dSmrg RegionPtr clipBoxes 558fc5a983dSmrg) 559fc5a983dSmrg{ 560fc5a983dSmrg NVPtr pNv = NVPTR(pScrnInfo); 561fc5a983dSmrg NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv); 562fc5a983dSmrg BoxPtr pbox = REGION_RECTS(clipBoxes); 563fc5a983dSmrg int nbox = REGION_NUM_RECTS(clipBoxes); 564fc5a983dSmrg CARD32 dsdx, dtdy, size, point, srcpoint, format; 565fc5a983dSmrg 566fc5a983dSmrg dsdx = (src_w << 20) / drw_w; 567fc5a983dSmrg dtdy = (src_h << 20) / drw_h; 568fc5a983dSmrg 569fc5a983dSmrg size = ((dstBox->y2 - dstBox->y1) << 16) | (dstBox->x2 - dstBox->x1); 570fc5a983dSmrg point = (dstBox->y1 << 16) | dstBox->x1; 571fc5a983dSmrg 572fc5a983dSmrg dstPitch |= (STRETCH_BLIT_SRC_FORMAT_ORIGIN_CENTER << 16) | 573fc5a983dSmrg (STRETCH_BLIT_SRC_FORMAT_FILTER_BILINEAR << 24); 574fc5a983dSmrg 575fc5a983dSmrg srcpoint = ((y1 << 4) & 0xffff0000) | (x1 >> 12); 576fc5a983dSmrg 577fc5a983dSmrg switch(id) { 578fc5a983dSmrg case FOURCC_RGB: 579fc5a983dSmrg format = STRETCH_BLIT_FORMAT_X8R8G8B8; 580fc5a983dSmrg break; 581fc5a983dSmrg case FOURCC_UYVY: 582fc5a983dSmrg format = STRETCH_BLIT_FORMAT_UYVY; 583fc5a983dSmrg break; 584fc5a983dSmrg default: 585fc5a983dSmrg format = STRETCH_BLIT_FORMAT_YUYV; 586fc5a983dSmrg break; 587fc5a983dSmrg } 588fc5a983dSmrg 589fc5a983dSmrg if(pNv->CurrentLayout.depth == 15) { 590fc5a983dSmrg NVDmaStart(pNv, SURFACE_FORMAT, 1); 591fc5a983dSmrg NVDmaNext (pNv, SURFACE_FORMAT_DEPTH15); 592fc5a983dSmrg } 593fc5a983dSmrg 594fc5a983dSmrg if(pPriv->SyncToVBlank) { 595fc5a983dSmrg NVDmaKickoff(pNv); 596fc5a983dSmrg NVWaitVSync(pNv); 597fc5a983dSmrg } 598fc5a983dSmrg 599fc5a983dSmrg if(pNv->BlendingPossible) { 600fc5a983dSmrg NVDmaStart(pNv, STRETCH_BLIT_FORMAT, 2); 601fc5a983dSmrg NVDmaNext (pNv, format); 602fc5a983dSmrg NVDmaNext (pNv, STRETCH_BLIT_OPERATION_COPY); 603fc5a983dSmrg } else { 604fc5a983dSmrg NVDmaStart(pNv, STRETCH_BLIT_FORMAT, 1); 605fc5a983dSmrg NVDmaNext (pNv, format); 606fc5a983dSmrg } 607fc5a983dSmrg 608fc5a983dSmrg while(nbox--) { 609fc5a983dSmrg NVDmaStart(pNv, RECT_SOLID_COLOR, 1); 610fc5a983dSmrg NVDmaNext (pNv, 0); 611fc5a983dSmrg 612fc5a983dSmrg NVDmaStart(pNv, STRETCH_BLIT_CLIP_POINT, 6); 613fc5a983dSmrg NVDmaNext (pNv, (pbox->y1 << 16) | pbox->x1); 614fc5a983dSmrg NVDmaNext (pNv, ((pbox->y2 - pbox->y1) << 16) | (pbox->x2 - pbox->x1)); 615fc5a983dSmrg NVDmaNext (pNv, point); 616fc5a983dSmrg NVDmaNext (pNv, size); 617fc5a983dSmrg NVDmaNext (pNv, dsdx); 618fc5a983dSmrg NVDmaNext (pNv, dtdy); 619fc5a983dSmrg 620fc5a983dSmrg NVDmaStart(pNv, STRETCH_BLIT_SRC_SIZE, 4); 621fc5a983dSmrg NVDmaNext (pNv, (height << 16) | width); 622fc5a983dSmrg NVDmaNext (pNv, dstPitch); 623fc5a983dSmrg NVDmaNext (pNv, offset); 624fc5a983dSmrg NVDmaNext (pNv, srcpoint); 625fc5a983dSmrg pbox++; 626fc5a983dSmrg } 627fc5a983dSmrg 628fc5a983dSmrg if(pNv->CurrentLayout.depth == 15) { 629fc5a983dSmrg NVDmaStart(pNv, SURFACE_FORMAT, 1); 630fc5a983dSmrg NVDmaNext (pNv, SURFACE_FORMAT_DEPTH16); 631fc5a983dSmrg } 632fc5a983dSmrg 633fc5a983dSmrg NVDmaKickoff(pNv); 634fc5a983dSmrg SET_SYNC_FLAG(pNv->AccelInfoRec); 635fc5a983dSmrg 636fc5a983dSmrg pPriv->videoStatus = FREE_TIMER; 637fc5a983dSmrg pPriv->videoTime = currentTime.milliseconds + FREE_DELAY; 638fc5a983dSmrg pNv->VideoTimerCallback = NVVideoTimerCallback; 639fc5a983dSmrg} 640fc5a983dSmrg 641fc5a983dSmrg/* 642fc5a983dSmrg * StopVideo 643fc5a983dSmrg */ 644fc5a983dSmrgstatic void NVStopOverlayVideo 645fc5a983dSmrg( 646fc5a983dSmrg ScrnInfoPtr pScrnInfo, 647fc5a983dSmrg pointer data, 648fc5a983dSmrg Bool Exit 649fc5a983dSmrg) 650fc5a983dSmrg{ 651fc5a983dSmrg NVPtr pNv = NVPTR(pScrnInfo); 652fc5a983dSmrg NVPortPrivPtr pPriv = (NVPortPrivPtr)data; 653fc5a983dSmrg 654fc5a983dSmrg if(pPriv->grabbedByV4L) return; 655fc5a983dSmrg 656fc5a983dSmrg REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip); 657fc5a983dSmrg 658fc5a983dSmrg if(Exit) { 659fc5a983dSmrg if(pPriv->videoStatus & CLIENT_VIDEO_ON) 660fc5a983dSmrg NVStopOverlay(pScrnInfo); 661fc5a983dSmrg NVFreeOverlayMemory(pScrnInfo); 662fc5a983dSmrg pPriv->videoStatus = 0; 663fc5a983dSmrg } else { 664fc5a983dSmrg if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 665fc5a983dSmrg pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON; 666fc5a983dSmrg pPriv->videoTime = currentTime.milliseconds + OFF_DELAY; 667fc5a983dSmrg pNv->VideoTimerCallback = NVVideoTimerCallback; 668fc5a983dSmrg } 669fc5a983dSmrg } 670fc5a983dSmrg} 671fc5a983dSmrg 672fc5a983dSmrgstatic void NVStopBlitVideo 673fc5a983dSmrg( 674fc5a983dSmrg ScrnInfoPtr pScrnInfo, 675fc5a983dSmrg pointer data, 676fc5a983dSmrg Bool Exit 677fc5a983dSmrg) 678fc5a983dSmrg{ 679fc5a983dSmrg} 680fc5a983dSmrg 681fc5a983dSmrgstatic int NVSetOverlayPortAttribute 682fc5a983dSmrg( 683fc5a983dSmrg ScrnInfoPtr pScrnInfo, 684fc5a983dSmrg Atom attribute, 685fc5a983dSmrg INT32 value, 686fc5a983dSmrg pointer data 687fc5a983dSmrg) 688fc5a983dSmrg{ 689fc5a983dSmrg NVPortPrivPtr pPriv = (NVPortPrivPtr)data; 690fc5a983dSmrg 691fc5a983dSmrg if (attribute == xvBrightness) 692fc5a983dSmrg { 693fc5a983dSmrg if ((value < -512) || (value > 512)) 694fc5a983dSmrg return BadValue; 695fc5a983dSmrg pPriv->brightness = value; 696fc5a983dSmrg } 697fc5a983dSmrg else if (attribute == xvDoubleBuffer) 698fc5a983dSmrg { 699fc5a983dSmrg if ((value < 0) || (value > 1)) 700fc5a983dSmrg return BadValue; 701fc5a983dSmrg pPriv->doubleBuffer = value; 702fc5a983dSmrg } 703fc5a983dSmrg else if (attribute == xvContrast) 704fc5a983dSmrg { 705fc5a983dSmrg if ((value < 0) || (value > 8191)) 706fc5a983dSmrg return BadValue; 707fc5a983dSmrg pPriv->contrast = value; 708fc5a983dSmrg } 709fc5a983dSmrg else if (attribute == xvHue) 710fc5a983dSmrg { 711fc5a983dSmrg value %= 360; 712fc5a983dSmrg if (value < 0) 713fc5a983dSmrg value += 360; 714fc5a983dSmrg pPriv->hue = value; 715fc5a983dSmrg } 716fc5a983dSmrg else if (attribute == xvSaturation) 717fc5a983dSmrg { 718fc5a983dSmrg if ((value < 0) || (value > 8191)) 719fc5a983dSmrg return BadValue; 720fc5a983dSmrg pPriv->saturation = value; 721fc5a983dSmrg } 722fc5a983dSmrg else if (attribute == xvColorKey) 723fc5a983dSmrg { 724fc5a983dSmrg pPriv->colorKey = value; 725fc5a983dSmrg REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip); 726fc5a983dSmrg } 727fc5a983dSmrg else if (attribute == xvAutopaintColorKey) 728fc5a983dSmrg { 729fc5a983dSmrg if ((value < 0) || (value > 1)) 730fc5a983dSmrg return BadValue; 731fc5a983dSmrg pPriv->autopaintColorKey = value; 732fc5a983dSmrg } 733fc5a983dSmrg else if (attribute == xvITURBT709) 734fc5a983dSmrg { 735fc5a983dSmrg if ((value < 0) || (value > 1)) 736fc5a983dSmrg return BadValue; 737fc5a983dSmrg pPriv->iturbt_709 = value; 738fc5a983dSmrg } 739fc5a983dSmrg else if (attribute == xvSetDefaults) 740fc5a983dSmrg { 741fc5a983dSmrg NVSetPortDefaults(pScrnInfo, pPriv); 742fc5a983dSmrg } 743fc5a983dSmrg else 744fc5a983dSmrg return BadMatch; 745fc5a983dSmrg 746fc5a983dSmrg NVResetVideo(pScrnInfo); 747fc5a983dSmrg return Success; 748fc5a983dSmrg} 749fc5a983dSmrg 750fc5a983dSmrg 751fc5a983dSmrgstatic int NVGetOverlayPortAttribute 752fc5a983dSmrg( 753fc5a983dSmrg ScrnInfoPtr pScrnInfo, 754fc5a983dSmrg Atom attribute, 755fc5a983dSmrg INT32 *value, 756fc5a983dSmrg pointer data 757fc5a983dSmrg) 758fc5a983dSmrg{ 759fc5a983dSmrg NVPortPrivPtr pPriv = (NVPortPrivPtr)data; 760fc5a983dSmrg 761fc5a983dSmrg if (attribute == xvBrightness) 762fc5a983dSmrg *value = pPriv->brightness; 763fc5a983dSmrg else if (attribute == xvDoubleBuffer) 764fc5a983dSmrg *value = (pPriv->doubleBuffer) ? 1 : 0; 765fc5a983dSmrg else if (attribute == xvContrast) 766fc5a983dSmrg *value = pPriv->contrast; 767fc5a983dSmrg else if (attribute == xvSaturation) 768fc5a983dSmrg *value = pPriv->saturation; 769fc5a983dSmrg else if (attribute == xvHue) 770fc5a983dSmrg *value = pPriv->hue; 771fc5a983dSmrg else if (attribute == xvColorKey) 772fc5a983dSmrg *value = pPriv->colorKey; 773fc5a983dSmrg else if (attribute == xvAutopaintColorKey) 774fc5a983dSmrg *value = (pPriv->autopaintColorKey) ? 1 : 0; 775fc5a983dSmrg else if (attribute == xvITURBT709) 776fc5a983dSmrg *value = (pPriv->iturbt_709) ? 1 : 0; 777fc5a983dSmrg else 778fc5a983dSmrg return BadMatch; 779fc5a983dSmrg 780fc5a983dSmrg return Success; 781fc5a983dSmrg} 782fc5a983dSmrg 783fc5a983dSmrgstatic int NVSetBlitPortAttribute 784fc5a983dSmrg( 785fc5a983dSmrg ScrnInfoPtr pScrnInfo, 786fc5a983dSmrg Atom attribute, 787fc5a983dSmrg INT32 value, 788fc5a983dSmrg pointer data 789fc5a983dSmrg) 790fc5a983dSmrg{ 791fc5a983dSmrg NVPortPrivPtr pPriv = (NVPortPrivPtr)data; 792fc5a983dSmrg NVPtr pNv = NVPTR(pScrnInfo); 793fc5a983dSmrg 794fc5a983dSmrg if ((attribute == xvSyncToVBlank) && pNv->WaitVSyncPossible) { 795fc5a983dSmrg if ((value < 0) || (value > 1)) 796fc5a983dSmrg return BadValue; 797fc5a983dSmrg pPriv->SyncToVBlank = value; 798fc5a983dSmrg } else 799fc5a983dSmrg if (attribute == xvSetDefaults) { 800fc5a983dSmrg pPriv->SyncToVBlank = pNv->WaitVSyncPossible; 801fc5a983dSmrg } else 802fc5a983dSmrg return BadMatch; 803fc5a983dSmrg 804fc5a983dSmrg return Success; 805fc5a983dSmrg} 806fc5a983dSmrg 807fc5a983dSmrgstatic int NVGetBlitPortAttribute 808fc5a983dSmrg( 809fc5a983dSmrg ScrnInfoPtr pScrnInfo, 810fc5a983dSmrg Atom attribute, 811fc5a983dSmrg INT32 *value, 812fc5a983dSmrg pointer data 813fc5a983dSmrg) 814fc5a983dSmrg{ 815fc5a983dSmrg NVPortPrivPtr pPriv = (NVPortPrivPtr)data; 816fc5a983dSmrg 817fc5a983dSmrg if(attribute == xvSyncToVBlank) 818fc5a983dSmrg *value = (pPriv->SyncToVBlank) ? 1 : 0; 819fc5a983dSmrg else 820fc5a983dSmrg return BadMatch; 821fc5a983dSmrg 822fc5a983dSmrg return Success; 823fc5a983dSmrg} 824fc5a983dSmrg 825fc5a983dSmrg 826fc5a983dSmrg/* 827fc5a983dSmrg * QueryBestSize 828fc5a983dSmrg */ 829fc5a983dSmrgstatic void NVQueryBestSize 830fc5a983dSmrg( 831fc5a983dSmrg ScrnInfoPtr pScrnInfo, 832fc5a983dSmrg Bool motion, 833fc5a983dSmrg short vid_w, 834fc5a983dSmrg short vid_h, 835fc5a983dSmrg short drw_w, 836fc5a983dSmrg short drw_h, 837fc5a983dSmrg unsigned int *p_w, 838fc5a983dSmrg unsigned int *p_h, 839fc5a983dSmrg pointer data 840fc5a983dSmrg) 841fc5a983dSmrg{ 842fc5a983dSmrg if(vid_w > (drw_w << 3)) 843fc5a983dSmrg drw_w = vid_w >> 3; 844fc5a983dSmrg if(vid_h > (drw_h << 3)) 845fc5a983dSmrg drw_h = vid_h >> 3; 846fc5a983dSmrg 847fc5a983dSmrg *p_w = drw_w; 848fc5a983dSmrg *p_h = drw_h; 849fc5a983dSmrg} 850fc5a983dSmrg 851fc5a983dSmrgstatic void NVCopyData420 852fc5a983dSmrg( 853fc5a983dSmrg unsigned char *src1, 854fc5a983dSmrg unsigned char *src2, 855fc5a983dSmrg unsigned char *src3, 856fc5a983dSmrg unsigned char *dst1, 857fc5a983dSmrg int srcPitch, 858fc5a983dSmrg int srcPitch2, 859fc5a983dSmrg int dstPitch, 860fc5a983dSmrg int h, 861fc5a983dSmrg int w 862fc5a983dSmrg) 863fc5a983dSmrg{ 864fc5a983dSmrg CARD32 *dst; 865fc5a983dSmrg CARD8 *s1, *s2, *s3; 866fc5a983dSmrg int i, j; 867fc5a983dSmrg 868fc5a983dSmrg w >>= 1; 869fc5a983dSmrg 870fc5a983dSmrg for(j = 0; j < h; j++) { 871fc5a983dSmrg dst = (CARD32*)dst1; 872fc5a983dSmrg s1 = src1; s2 = src2; s3 = src3; 873fc5a983dSmrg i = w; 874fc5a983dSmrg while(i > 4) { 875fc5a983dSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN 876fc5a983dSmrg dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0]; 877fc5a983dSmrg dst[1] = (s1[2] << 24) | (s1[3] << 8) | (s3[1] << 16) | s2[1]; 878fc5a983dSmrg dst[2] = (s1[4] << 24) | (s1[5] << 8) | (s3[2] << 16) | s2[2]; 879fc5a983dSmrg dst[3] = (s1[6] << 24) | (s1[7] << 8) | (s3[3] << 16) | s2[3]; 880fc5a983dSmrg#else 881fc5a983dSmrg dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24); 882fc5a983dSmrg dst[1] = s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24); 883fc5a983dSmrg dst[2] = s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24); 884fc5a983dSmrg dst[3] = s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24); 885fc5a983dSmrg#endif 886fc5a983dSmrg dst += 4; s2 += 4; s3 += 4; s1 += 8; 887fc5a983dSmrg i -= 4; 888fc5a983dSmrg } 889fc5a983dSmrg 890fc5a983dSmrg while(i--) { 891fc5a983dSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN 892fc5a983dSmrg dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0]; 893fc5a983dSmrg#else 894fc5a983dSmrg dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24); 895fc5a983dSmrg#endif 896fc5a983dSmrg dst++; s2++; s3++; 897fc5a983dSmrg s1 += 2; 898fc5a983dSmrg } 899fc5a983dSmrg 900fc5a983dSmrg dst1 += dstPitch; 901fc5a983dSmrg src1 += srcPitch; 902fc5a983dSmrg if(j & 1) { 903fc5a983dSmrg src2 += srcPitch2; 904fc5a983dSmrg src3 += srcPitch2; 905fc5a983dSmrg } 906fc5a983dSmrg } 907fc5a983dSmrg} 908fc5a983dSmrg 909fc5a983dSmrg 910fc5a983dSmrgstatic void NVMoveDWORDS( 911fc5a983dSmrg CARD32* dest, 912fc5a983dSmrg CARD32* src, 913fc5a983dSmrg int dwords ) 914fc5a983dSmrg{ 915fc5a983dSmrg while(dwords & ~0x03) { 916fc5a983dSmrg *dest = *src; 917fc5a983dSmrg *(dest + 1) = *(src + 1); 918fc5a983dSmrg *(dest + 2) = *(src + 2); 919fc5a983dSmrg *(dest + 3) = *(src + 3); 920fc5a983dSmrg src += 4; 921fc5a983dSmrg dest += 4; 922fc5a983dSmrg dwords -= 4; 923fc5a983dSmrg } 924fc5a983dSmrg if(!dwords) return; 925fc5a983dSmrg *dest = *src; 926fc5a983dSmrg if(dwords == 1) return; 927fc5a983dSmrg *(dest + 1) = *(src + 1); 928fc5a983dSmrg if(dwords == 2) return; 929fc5a983dSmrg *(dest + 2) = *(src + 2); 930fc5a983dSmrg} 931fc5a983dSmrg 932fc5a983dSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN 933fc5a983dSmrgstatic void NVMoveDWORDSSwapped( 934fc5a983dSmrg CARD32* dest, 935fc5a983dSmrg CARD8* src, 936fc5a983dSmrg int dwords ) 937fc5a983dSmrg{ 938fc5a983dSmrg while(dwords--) { 939fc5a983dSmrg *dest++ = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0]; 940fc5a983dSmrg src += 4; 941fc5a983dSmrg } 942fc5a983dSmrg} 943fc5a983dSmrg#endif 944fc5a983dSmrg 945fc5a983dSmrgstatic void NVCopyData422 946fc5a983dSmrg( 947fc5a983dSmrg unsigned char *src, 948fc5a983dSmrg unsigned char *dst, 949fc5a983dSmrg int srcPitch, 950fc5a983dSmrg int dstPitch, 951fc5a983dSmrg int h, 952fc5a983dSmrg int w 953fc5a983dSmrg) 954fc5a983dSmrg{ 955fc5a983dSmrg w >>= 1; /* pixels to DWORDS */ 956fc5a983dSmrg while(h--) { 957fc5a983dSmrg NVMoveDWORDS((CARD32*)dst, (CARD32*)src, w); 958fc5a983dSmrg src += srcPitch; 959fc5a983dSmrg dst += dstPitch; 960fc5a983dSmrg } 961fc5a983dSmrg} 962fc5a983dSmrg 963fc5a983dSmrgstatic void NVCopyDataRGB 964fc5a983dSmrg( 965fc5a983dSmrg unsigned char *src, 966fc5a983dSmrg unsigned char *dst, 967fc5a983dSmrg int srcPitch, 968fc5a983dSmrg int dstPitch, 969fc5a983dSmrg int h, 970fc5a983dSmrg int w 971fc5a983dSmrg) 972fc5a983dSmrg{ 973fc5a983dSmrg while(h--) { 974fc5a983dSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN 975fc5a983dSmrg NVMoveDWORDSSwapped((CARD32*)dst, (CARD8*)src, w); 976fc5a983dSmrg#else 977fc5a983dSmrg NVMoveDWORDS((CARD32*)dst, (CARD32*)src, w); 978fc5a983dSmrg#endif 979fc5a983dSmrg src += srcPitch; 980fc5a983dSmrg dst += dstPitch; 981fc5a983dSmrg } 982fc5a983dSmrg} 983fc5a983dSmrg 984fc5a983dSmrg 985fc5a983dSmrg/* 986fc5a983dSmrg * PutImage 987fc5a983dSmrg */ 988fc5a983dSmrgstatic int NVPutImage 989fc5a983dSmrg( 990fc5a983dSmrg ScrnInfoPtr pScrnInfo, 991fc5a983dSmrg short src_x, 992fc5a983dSmrg short src_y, 993fc5a983dSmrg short drw_x, 994fc5a983dSmrg short drw_y, 995fc5a983dSmrg short src_w, 996fc5a983dSmrg short src_h, 997fc5a983dSmrg short drw_w, 998fc5a983dSmrg short drw_h, 999fc5a983dSmrg int id, 1000fc5a983dSmrg unsigned char *buf, 1001fc5a983dSmrg short width, 1002fc5a983dSmrg short height, 1003fc5a983dSmrg Bool Sync, 1004fc5a983dSmrg RegionPtr clipBoxes, 1005fc5a983dSmrg pointer data, 1006fc5a983dSmrg DrawablePtr pDraw 1007fc5a983dSmrg) 1008fc5a983dSmrg{ 1009fc5a983dSmrg NVPortPrivPtr pPriv = (NVPortPrivPtr)data; 1010fc5a983dSmrg NVPtr pNv = NVPTR(pScrnInfo); 1011fc5a983dSmrg INT32 xa, xb, ya, yb; 1012fc5a983dSmrg unsigned char *dst_start; 1013fc5a983dSmrg int newSize, offset, s2offset, s3offset; 1014fc5a983dSmrg int srcPitch, srcPitch2, dstPitch; 1015fc5a983dSmrg int top, left, right, bottom, npixels, nlines, bpp; 1016fc5a983dSmrg Bool skip = FALSE; 1017fc5a983dSmrg BoxRec dstBox; 1018fc5a983dSmrg CARD32 tmp; 1019fc5a983dSmrg 1020fc5a983dSmrg /* 1021fc5a983dSmrg * s2offset, s3offset - byte offsets into U and V plane of the 1022fc5a983dSmrg * source where copying starts. Y plane is 1023fc5a983dSmrg * done by editing "buf". 1024fc5a983dSmrg * 1025fc5a983dSmrg * offset - byte offset to the first line of the destination. 1026fc5a983dSmrg * 1027fc5a983dSmrg * dst_start - byte address to the first displayed pel. 1028fc5a983dSmrg * 1029fc5a983dSmrg */ 1030fc5a983dSmrg 1031fc5a983dSmrg if(pPriv->grabbedByV4L) return Success; 1032fc5a983dSmrg 1033fc5a983dSmrg /* make the compiler happy */ 1034fc5a983dSmrg s2offset = s3offset = srcPitch2 = 0; 1035fc5a983dSmrg 1036fc5a983dSmrg if(!pPriv->blitter) { 1037fc5a983dSmrg if(src_w > (drw_w << 3)) 1038fc5a983dSmrg drw_w = src_w >> 3; 1039fc5a983dSmrg if(src_h > (drw_h << 3)) 1040fc5a983dSmrg drw_h = src_h >> 3; 1041fc5a983dSmrg } 1042fc5a983dSmrg 1043fc5a983dSmrg /* Clip */ 1044fc5a983dSmrg xa = src_x; 1045fc5a983dSmrg xb = src_x + src_w; 1046fc5a983dSmrg ya = src_y; 1047fc5a983dSmrg yb = src_y + src_h; 1048fc5a983dSmrg 1049fc5a983dSmrg dstBox.x1 = drw_x; 1050fc5a983dSmrg dstBox.x2 = drw_x + drw_w; 1051fc5a983dSmrg dstBox.y1 = drw_y; 1052fc5a983dSmrg dstBox.y2 = drw_y + drw_h; 1053fc5a983dSmrg 1054fc5a983dSmrg if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, 1055fc5a983dSmrg width, height)) 1056fc5a983dSmrg return Success; 1057fc5a983dSmrg 1058fc5a983dSmrg if(!pPriv->blitter) { 1059fc5a983dSmrg dstBox.x1 -= pScrnInfo->frameX0; 1060fc5a983dSmrg dstBox.x2 -= pScrnInfo->frameX0; 1061fc5a983dSmrg dstBox.y1 -= pScrnInfo->frameY0; 1062fc5a983dSmrg dstBox.y2 -= pScrnInfo->frameY0; 1063fc5a983dSmrg } 1064fc5a983dSmrg 1065fc5a983dSmrg bpp = pScrnInfo->bitsPerPixel >> 3; 1066fc5a983dSmrg 1067fc5a983dSmrg switch(id) { 1068fc5a983dSmrg case FOURCC_YV12: 1069fc5a983dSmrg case FOURCC_I420: 1070fc5a983dSmrg srcPitch = (width + 3) & ~3; /* of luma */ 1071fc5a983dSmrg s2offset = srcPitch * height; 1072fc5a983dSmrg srcPitch2 = ((width >> 1) + 3) & ~3; 1073fc5a983dSmrg s3offset = (srcPitch2 * (height >> 1)) + s2offset; 1074fc5a983dSmrg dstPitch = ((width << 1) + 63) & ~63; 1075fc5a983dSmrg break; 1076fc5a983dSmrg case FOURCC_UYVY: 1077fc5a983dSmrg case FOURCC_YUY2: 1078fc5a983dSmrg srcPitch = width << 1; 1079fc5a983dSmrg dstPitch = ((width << 1) + 63) & ~63; 1080fc5a983dSmrg break; 1081fc5a983dSmrg case FOURCC_RGB: 1082fc5a983dSmrg srcPitch = width << 2; 1083fc5a983dSmrg dstPitch = ((width << 2) + 63) & ~63; 1084fc5a983dSmrg break; 1085fc5a983dSmrg default: 1086fc5a983dSmrg return BadImplementation; 1087fc5a983dSmrg } 1088fc5a983dSmrg 1089fc5a983dSmrg newSize = height * dstPitch / bpp; 1090fc5a983dSmrg 1091fc5a983dSmrg if(pPriv->doubleBuffer) 1092fc5a983dSmrg newSize <<= 1; 1093fc5a983dSmrg 1094fc5a983dSmrg pPriv->linear = NVAllocateOverlayMemory(pScrnInfo, 1095fc5a983dSmrg pPriv->linear, 1096fc5a983dSmrg newSize); 1097fc5a983dSmrg 1098fc5a983dSmrg if(!pPriv->linear) return BadAlloc; 1099fc5a983dSmrg 1100fc5a983dSmrg offset = pPriv->linear->offset * bpp; 1101fc5a983dSmrg 1102fc5a983dSmrg if(pPriv->doubleBuffer) { 1103fc5a983dSmrg int mask = 1 << (pPriv->currentBuffer << 2); 1104fc5a983dSmrg 1105fc5a983dSmrg#if 0 1106fc5a983dSmrg /* burn the CPU until the next buffer is available */ 1107fc5a983dSmrg while(pNv->PMC[0x00008700/4] & mask); 1108fc5a983dSmrg#else 1109fc5a983dSmrg /* overwrite the newest buffer if there's not one free */ 1110fc5a983dSmrg if(pNv->PMC[0x00008700/4] & mask) { 1111fc5a983dSmrg if(!pPriv->currentBuffer) 1112fc5a983dSmrg offset += (newSize * bpp) >> 1; 1113fc5a983dSmrg skip = TRUE; 1114fc5a983dSmrg } else 1115fc5a983dSmrg#endif 1116fc5a983dSmrg if(pPriv->currentBuffer) 1117fc5a983dSmrg offset += (newSize * bpp) >> 1; 1118fc5a983dSmrg } 1119fc5a983dSmrg 1120fc5a983dSmrg dst_start = pNv->FbStart + offset; 1121fc5a983dSmrg 1122fc5a983dSmrg /* We need to enlarge the copied rectangle by a pixel so the HW 1123fc5a983dSmrg filtering doesn't pick up junk laying outside of the source */ 1124fc5a983dSmrg 1125fc5a983dSmrg left = (xa - 0x00010000) >> 16; 1126fc5a983dSmrg if(left < 0) left = 0; 1127fc5a983dSmrg top = (ya - 0x00010000) >> 16; 1128fc5a983dSmrg if(top < 0) top = 0; 1129fc5a983dSmrg right = (xb + 0x0001ffff) >> 16; 1130fc5a983dSmrg if(right > width) right = width; 1131fc5a983dSmrg bottom = (yb + 0x0001ffff) >> 16; 1132fc5a983dSmrg if(bottom > height) bottom = height; 1133fc5a983dSmrg 1134fc5a983dSmrg if(pPriv->blitter) NVSync(pScrnInfo); 1135fc5a983dSmrg 1136fc5a983dSmrg switch(id) { 1137fc5a983dSmrg case FOURCC_YV12: 1138fc5a983dSmrg case FOURCC_I420: 1139fc5a983dSmrg left &= ~1; 1140fc5a983dSmrg npixels = ((right + 1) & ~1) - left; 1141fc5a983dSmrg top &= ~1; 1142fc5a983dSmrg nlines = ((bottom + 1) & ~1) - top; 1143fc5a983dSmrg 1144fc5a983dSmrg dst_start += (left << 1) + (top * dstPitch); 1145fc5a983dSmrg tmp = ((top >> 1) * srcPitch2) + (left >> 1); 1146fc5a983dSmrg s2offset += tmp; 1147fc5a983dSmrg s3offset += tmp; 1148fc5a983dSmrg if(id == FOURCC_I420) { 1149fc5a983dSmrg tmp = s2offset; 1150fc5a983dSmrg s2offset = s3offset; 1151fc5a983dSmrg s3offset = tmp; 1152fc5a983dSmrg } 1153fc5a983dSmrg NVCopyData420(buf + (top * srcPitch) + left, 1154fc5a983dSmrg buf + s2offset, buf + s3offset, 1155fc5a983dSmrg dst_start, srcPitch, srcPitch2, 1156fc5a983dSmrg dstPitch, nlines, npixels); 1157fc5a983dSmrg break; 1158fc5a983dSmrg case FOURCC_UYVY: 1159fc5a983dSmrg case FOURCC_YUY2: 1160fc5a983dSmrg left &= ~1; 1161fc5a983dSmrg npixels = ((right + 1) & ~1) - left; 1162fc5a983dSmrg nlines = bottom - top; 1163fc5a983dSmrg 1164fc5a983dSmrg left <<= 1; 1165fc5a983dSmrg buf += (top * srcPitch) + left; 1166fc5a983dSmrg dst_start += left + (top * dstPitch); 1167fc5a983dSmrg 1168fc5a983dSmrg NVCopyData422(buf, dst_start, srcPitch, dstPitch, nlines, npixels); 1169fc5a983dSmrg break; 1170fc5a983dSmrg case FOURCC_RGB: 1171fc5a983dSmrg npixels = right - left; 1172fc5a983dSmrg nlines = bottom - top; 1173fc5a983dSmrg 1174fc5a983dSmrg left <<= 2; 1175fc5a983dSmrg buf += (top * srcPitch) + left; 1176fc5a983dSmrg dst_start += left + (top * dstPitch); 1177fc5a983dSmrg 1178fc5a983dSmrg NVCopyDataRGB(buf, dst_start, srcPitch, dstPitch, nlines, npixels); 1179fc5a983dSmrg break; 1180fc5a983dSmrg default: 1181fc5a983dSmrg return BadImplementation; 1182fc5a983dSmrg } 1183fc5a983dSmrg 1184fc5a983dSmrg if(!skip) { 1185fc5a983dSmrg if(pPriv->blitter) { 1186fc5a983dSmrg NVPutBlitImage(pScrnInfo, offset, id, dstPitch, &dstBox, 1187fc5a983dSmrg xa, ya, xb, yb, 1188fc5a983dSmrg width, height, src_w, src_h, drw_w, drw_h, 1189fc5a983dSmrg clipBoxes); 1190fc5a983dSmrg } else { 1191fc5a983dSmrg NVPutOverlayImage(pScrnInfo, offset, id, dstPitch, &dstBox, 1192fc5a983dSmrg xa, ya, xb, yb, 1193fc5a983dSmrg width, height, src_w, src_h, drw_w, drw_h, 1194fc5a983dSmrg clipBoxes); 1195fc5a983dSmrg pPriv->currentBuffer ^= 1; 1196fc5a983dSmrg } 1197fc5a983dSmrg } 1198fc5a983dSmrg 1199fc5a983dSmrg return Success; 1200fc5a983dSmrg} 1201fc5a983dSmrg/* 1202fc5a983dSmrg * QueryImageAttributes 1203fc5a983dSmrg */ 1204fc5a983dSmrgstatic int NVQueryImageAttributes 1205fc5a983dSmrg( 1206fc5a983dSmrg ScrnInfoPtr pScrnInfo, 1207fc5a983dSmrg int id, 1208fc5a983dSmrg unsigned short *w, 1209fc5a983dSmrg unsigned short *h, 1210fc5a983dSmrg int *pitches, 1211fc5a983dSmrg int *offsets 1212fc5a983dSmrg) 1213fc5a983dSmrg{ 1214fc5a983dSmrg int size, tmp; 1215fc5a983dSmrg 1216fc5a983dSmrg if(*w > 2046) 1217fc5a983dSmrg *w = 2046; 1218fc5a983dSmrg if(*h > 2046) 1219fc5a983dSmrg *h = 2046; 1220fc5a983dSmrg 1221fc5a983dSmrg *w = (*w + 1) & ~1; 1222fc5a983dSmrg if (offsets) 1223fc5a983dSmrg offsets[0] = 0; 1224fc5a983dSmrg 1225fc5a983dSmrg switch (id) 1226fc5a983dSmrg { 1227fc5a983dSmrg case FOURCC_YV12: 1228fc5a983dSmrg case FOURCC_I420: 1229fc5a983dSmrg *h = (*h + 1) & ~1; 1230fc5a983dSmrg size = (*w + 3) & ~3; 1231fc5a983dSmrg if (pitches) 1232fc5a983dSmrg pitches[0] = size; 1233fc5a983dSmrg size *= *h; 1234fc5a983dSmrg if (offsets) 1235fc5a983dSmrg offsets[1] = size; 1236fc5a983dSmrg tmp = ((*w >> 1) + 3) & ~3; 1237fc5a983dSmrg if (pitches) 1238fc5a983dSmrg pitches[1] = pitches[2] = tmp; 1239fc5a983dSmrg tmp *= (*h >> 1); 1240fc5a983dSmrg size += tmp; 1241fc5a983dSmrg if (offsets) 1242fc5a983dSmrg offsets[2] = size; 1243fc5a983dSmrg size += tmp; 1244fc5a983dSmrg break; 1245fc5a983dSmrg case FOURCC_UYVY: 1246fc5a983dSmrg case FOURCC_YUY2: 1247fc5a983dSmrg size = *w << 1; 1248fc5a983dSmrg if (pitches) 1249fc5a983dSmrg pitches[0] = size; 1250fc5a983dSmrg size *= *h; 1251fc5a983dSmrg break; 1252fc5a983dSmrg case FOURCC_RGB: 1253fc5a983dSmrg size = *w << 2; 1254fc5a983dSmrg if(pitches) 1255fc5a983dSmrg pitches[0] = size; 1256fc5a983dSmrg size *= *h; 1257fc5a983dSmrg break; 1258fc5a983dSmrg default: 1259fc5a983dSmrg *w = *h = size = 0; 1260fc5a983dSmrg break; 1261fc5a983dSmrg } 1262fc5a983dSmrg return size; 1263fc5a983dSmrg} 1264fc5a983dSmrg 1265fc5a983dSmrgstatic void NVVideoTimerCallback 1266fc5a983dSmrg( 1267fc5a983dSmrg ScrnInfoPtr pScrnInfo, 1268fc5a983dSmrg Time currentTime 1269fc5a983dSmrg) 1270fc5a983dSmrg{ 1271fc5a983dSmrg NVPtr pNv = NVPTR(pScrnInfo); 1272fc5a983dSmrg NVPortPrivPtr pOverPriv = NULL; 1273fc5a983dSmrg NVPortPrivPtr pBlitPriv = NULL; 1274fc5a983dSmrg Bool needCallback = FALSE; 1275fc5a983dSmrg 1276fc5a983dSmrg if(!pScrnInfo->vtSema) return; 1277fc5a983dSmrg 1278fc5a983dSmrg if(pNv->overlayAdaptor) { 1279fc5a983dSmrg pOverPriv = GET_OVERLAY_PRIVATE(pNv); 1280fc5a983dSmrg if(!pOverPriv->videoStatus) 1281fc5a983dSmrg pOverPriv = NULL; 1282fc5a983dSmrg } 1283fc5a983dSmrg 1284fc5a983dSmrg if(pNv->blitAdaptor) { 1285fc5a983dSmrg pBlitPriv = GET_BLIT_PRIVATE(pNv); 1286fc5a983dSmrg if(!pBlitPriv->videoStatus) 1287fc5a983dSmrg pBlitPriv = NULL; 1288fc5a983dSmrg } 1289fc5a983dSmrg 1290fc5a983dSmrg if(pOverPriv) { 1291fc5a983dSmrg if(pOverPriv->videoTime < currentTime) { 1292fc5a983dSmrg if(pOverPriv->videoStatus & OFF_TIMER) { 1293fc5a983dSmrg NVStopOverlay(pScrnInfo); 1294fc5a983dSmrg pOverPriv->videoStatus = FREE_TIMER; 1295fc5a983dSmrg pOverPriv->videoTime = currentTime + FREE_DELAY; 1296fc5a983dSmrg needCallback = TRUE; 1297fc5a983dSmrg } else 1298fc5a983dSmrg if(pOverPriv->videoStatus & FREE_TIMER) { 1299fc5a983dSmrg NVFreeOverlayMemory(pScrnInfo); 1300fc5a983dSmrg pOverPriv->videoStatus = 0; 1301fc5a983dSmrg } 1302fc5a983dSmrg } else { 1303fc5a983dSmrg needCallback = TRUE; 1304fc5a983dSmrg } 1305fc5a983dSmrg } 1306fc5a983dSmrg 1307fc5a983dSmrg if(pBlitPriv) { 1308fc5a983dSmrg if(pBlitPriv->videoTime < currentTime) { 1309fc5a983dSmrg NVFreeBlitMemory(pScrnInfo); 1310fc5a983dSmrg pBlitPriv->videoStatus = 0; 1311fc5a983dSmrg } else { 1312fc5a983dSmrg needCallback = TRUE; 1313fc5a983dSmrg } 1314fc5a983dSmrg } 1315fc5a983dSmrg 1316fc5a983dSmrg pNv->VideoTimerCallback = needCallback ? NVVideoTimerCallback : NULL; 1317fc5a983dSmrg} 1318fc5a983dSmrg 1319fc5a983dSmrg 1320fc5a983dSmrg/***** Exported offscreen surface stuff ****/ 1321fc5a983dSmrg 1322fc5a983dSmrg 1323fc5a983dSmrgstatic int 1324fc5a983dSmrgNVAllocSurface ( 1325fc5a983dSmrg ScrnInfoPtr pScrnInfo, 1326fc5a983dSmrg int id, 1327fc5a983dSmrg unsigned short w, 1328fc5a983dSmrg unsigned short h, 1329fc5a983dSmrg XF86SurfacePtr surface 1330fc5a983dSmrg) 1331fc5a983dSmrg{ 1332fc5a983dSmrg NVPtr pNv = NVPTR(pScrnInfo); 1333fc5a983dSmrg NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); 1334fc5a983dSmrg int size, bpp; 1335fc5a983dSmrg 1336fc5a983dSmrg bpp = pScrnInfo->bitsPerPixel >> 3; 1337fc5a983dSmrg 1338fc5a983dSmrg if(pPriv->grabbedByV4L) return BadAlloc; 1339fc5a983dSmrg 1340fc5a983dSmrg if((w > 2046) || (h > 2046)) return BadValue; 1341fc5a983dSmrg 1342fc5a983dSmrg w = (w + 1) & ~1; 1343fc5a983dSmrg pPriv->pitch = ((w << 1) + 63) & ~63; 1344fc5a983dSmrg size = h * pPriv->pitch / bpp; 1345fc5a983dSmrg 1346fc5a983dSmrg pPriv->linear = NVAllocateOverlayMemory(pScrnInfo, pPriv->linear, 1347fc5a983dSmrg size); 1348fc5a983dSmrg 1349fc5a983dSmrg if(!pPriv->linear) return BadAlloc; 1350fc5a983dSmrg 1351fc5a983dSmrg pPriv->offset = pPriv->linear->offset * bpp; 1352fc5a983dSmrg 1353fc5a983dSmrg surface->width = w; 1354fc5a983dSmrg surface->height = h; 1355fc5a983dSmrg surface->pScrn = pScrnInfo; 1356fc5a983dSmrg surface->pitches = &pPriv->pitch; 1357fc5a983dSmrg surface->offsets = &pPriv->offset; 1358fc5a983dSmrg surface->devPrivate.ptr = (pointer)pPriv; 1359fc5a983dSmrg surface->id = id; 1360fc5a983dSmrg 1361fc5a983dSmrg /* grab the video */ 1362fc5a983dSmrg NVStopOverlay(pScrnInfo); 1363fc5a983dSmrg pPriv->videoStatus = 0; 1364fc5a983dSmrg REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip); 1365fc5a983dSmrg pPriv->grabbedByV4L = TRUE; 1366fc5a983dSmrg 1367fc5a983dSmrg return Success; 1368fc5a983dSmrg} 1369fc5a983dSmrg 1370fc5a983dSmrgstatic int 1371fc5a983dSmrgNVStopSurface (XF86SurfacePtr surface) 1372fc5a983dSmrg{ 1373fc5a983dSmrg NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr); 1374fc5a983dSmrg 1375fc5a983dSmrg if(pPriv->grabbedByV4L && pPriv->videoStatus) { 1376fc5a983dSmrg NVStopOverlay(surface->pScrn); 1377fc5a983dSmrg pPriv->videoStatus = 0; 1378fc5a983dSmrg } 1379fc5a983dSmrg 1380fc5a983dSmrg return Success; 1381fc5a983dSmrg} 1382fc5a983dSmrg 1383fc5a983dSmrgstatic int 1384fc5a983dSmrgNVFreeSurface (XF86SurfacePtr surface) 1385fc5a983dSmrg{ 1386fc5a983dSmrg NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr); 1387fc5a983dSmrg 1388fc5a983dSmrg if(pPriv->grabbedByV4L) { 1389fc5a983dSmrg NVStopSurface(surface); 1390fc5a983dSmrg NVFreeOverlayMemory(surface->pScrn); 1391fc5a983dSmrg pPriv->grabbedByV4L = FALSE; 1392fc5a983dSmrg } 1393fc5a983dSmrg 1394fc5a983dSmrg return Success; 1395fc5a983dSmrg} 1396fc5a983dSmrg 1397fc5a983dSmrgstatic int 1398fc5a983dSmrgNVGetSurfaceAttribute ( 1399fc5a983dSmrg ScrnInfoPtr pScrnInfo, 1400fc5a983dSmrg Atom attribute, 1401fc5a983dSmrg INT32 *value 1402fc5a983dSmrg) 1403fc5a983dSmrg{ 1404fc5a983dSmrg NVPtr pNv = NVPTR(pScrnInfo); 1405fc5a983dSmrg NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); 1406fc5a983dSmrg 1407fc5a983dSmrg return NVGetOverlayPortAttribute(pScrnInfo, attribute, value, (pointer)pPriv); 1408fc5a983dSmrg} 1409fc5a983dSmrg 1410fc5a983dSmrgstatic int 1411fc5a983dSmrgNVSetSurfaceAttribute( 1412fc5a983dSmrg ScrnInfoPtr pScrnInfo, 1413fc5a983dSmrg Atom attribute, 1414fc5a983dSmrg INT32 value 1415fc5a983dSmrg) 1416fc5a983dSmrg{ 1417fc5a983dSmrg NVPtr pNv = NVPTR(pScrnInfo); 1418fc5a983dSmrg NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); 1419fc5a983dSmrg 1420fc5a983dSmrg return NVSetOverlayPortAttribute(pScrnInfo, attribute, value, (pointer)pPriv); 1421fc5a983dSmrg} 1422fc5a983dSmrg 1423fc5a983dSmrgstatic int 1424fc5a983dSmrgNVDisplaySurface ( 1425fc5a983dSmrg XF86SurfacePtr surface, 1426fc5a983dSmrg short src_x, short src_y, 1427fc5a983dSmrg short drw_x, short drw_y, 1428fc5a983dSmrg short src_w, short src_h, 1429fc5a983dSmrg short drw_w, short drw_h, 1430fc5a983dSmrg RegionPtr clipBoxes 1431fc5a983dSmrg) 1432fc5a983dSmrg{ 1433fc5a983dSmrg ScrnInfoPtr pScrnInfo = surface->pScrn; 1434fc5a983dSmrg NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr); 1435fc5a983dSmrg INT32 xa, xb, ya, yb; 1436fc5a983dSmrg BoxRec dstBox; 1437fc5a983dSmrg 1438fc5a983dSmrg if(!pPriv->grabbedByV4L) return Success; 1439fc5a983dSmrg 1440fc5a983dSmrg if(src_w > (drw_w << 3)) 1441fc5a983dSmrg drw_w = src_w >> 3; 1442fc5a983dSmrg if(src_h > (drw_h << 3)) 1443fc5a983dSmrg drw_h = src_h >> 3; 1444fc5a983dSmrg 1445fc5a983dSmrg /* Clip */ 1446fc5a983dSmrg xa = src_x; 1447fc5a983dSmrg xb = src_x + src_w; 1448fc5a983dSmrg ya = src_y; 1449fc5a983dSmrg yb = src_y + src_h; 1450fc5a983dSmrg 1451fc5a983dSmrg dstBox.x1 = drw_x; 1452fc5a983dSmrg dstBox.x2 = drw_x + drw_w; 1453fc5a983dSmrg dstBox.y1 = drw_y; 1454fc5a983dSmrg dstBox.y2 = drw_y + drw_h; 1455fc5a983dSmrg 1456fc5a983dSmrg if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, 1457fc5a983dSmrg surface->width, surface->height)) 1458fc5a983dSmrg { 1459fc5a983dSmrg return Success; 1460fc5a983dSmrg } 1461fc5a983dSmrg 1462fc5a983dSmrg dstBox.x1 -= pScrnInfo->frameX0; 1463fc5a983dSmrg dstBox.x2 -= pScrnInfo->frameX0; 1464fc5a983dSmrg dstBox.y1 -= pScrnInfo->frameY0; 1465fc5a983dSmrg dstBox.y2 -= pScrnInfo->frameY0; 1466fc5a983dSmrg 1467fc5a983dSmrg pPriv->currentBuffer = 0; 1468fc5a983dSmrg 1469fc5a983dSmrg NVPutOverlayImage (pScrnInfo, surface->offsets[0], surface->id, 1470fc5a983dSmrg surface->pitches[0], &dstBox, xa, ya, xb, yb, 1471fc5a983dSmrg surface->width, surface->height, src_w, src_h, 1472fc5a983dSmrg drw_w, drw_h, clipBoxes); 1473fc5a983dSmrg 1474fc5a983dSmrg return Success; 1475fc5a983dSmrg} 1476fc5a983dSmrg 1477fc5a983dSmrgXF86OffscreenImageRec NVOffscreenImages[2] = 1478fc5a983dSmrg{ 1479fc5a983dSmrg { 1480fc5a983dSmrg &NVImages[0], 1481fc5a983dSmrg VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, 1482fc5a983dSmrg NVAllocSurface, 1483fc5a983dSmrg NVFreeSurface, 1484fc5a983dSmrg NVDisplaySurface, 1485fc5a983dSmrg NVStopSurface, 1486fc5a983dSmrg NVGetSurfaceAttribute, 1487fc5a983dSmrg NVSetSurfaceAttribute, 1488fc5a983dSmrg 2046, 2046, 1489fc5a983dSmrg NUM_OVERLAY_ATTRIBUTES - 1, 1490fc5a983dSmrg &NVOverlayAttributes[1] 1491fc5a983dSmrg }, 1492fc5a983dSmrg { 1493fc5a983dSmrg &NVImages[2], 1494fc5a983dSmrg VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, 1495fc5a983dSmrg NVAllocSurface, 1496fc5a983dSmrg NVFreeSurface, 1497fc5a983dSmrg NVDisplaySurface, 1498fc5a983dSmrg NVStopSurface, 1499fc5a983dSmrg NVGetSurfaceAttribute, 1500fc5a983dSmrg NVSetSurfaceAttribute, 1501fc5a983dSmrg 2046, 2046, 1502fc5a983dSmrg NUM_OVERLAY_ATTRIBUTES - 1, 1503fc5a983dSmrg &NVOverlayAttributes[1] 1504fc5a983dSmrg }, 1505fc5a983dSmrg}; 1506fc5a983dSmrg 1507fc5a983dSmrgstatic void 1508fc5a983dSmrgNVInitOffscreenImages (ScreenPtr pScreen) 1509fc5a983dSmrg{ 1510fc5a983dSmrg xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2); 1511fc5a983dSmrg} 1512