1706f2543Smrg/* 2706f2543Smrg * XFree86 Xv DDX written by Mark Vojkovich (markv@valinux.com) 3706f2543Smrg */ 4706f2543Smrg/* 5706f2543Smrg * Copyright (c) 1998-2003 by The XFree86 Project, Inc. 6706f2543Smrg * 7706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 8706f2543Smrg * copy of this software and associated documentation files (the "Software"), 9706f2543Smrg * to deal in the Software without restriction, including without limitation 10706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 12706f2543Smrg * Software is furnished to do so, subject to the following conditions: 13706f2543Smrg * 14706f2543Smrg * The above copyright notice and this permission notice shall be included in 15706f2543Smrg * all copies or substantial portions of the Software. 16706f2543Smrg * 17706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20706f2543Smrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 21706f2543Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22706f2543Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23706f2543Smrg * OTHER DEALINGS IN THE SOFTWARE. 24706f2543Smrg * 25706f2543Smrg * Except as contained in this notice, the name of the copyright holder(s) 26706f2543Smrg * and author(s) shall not be used in advertising or otherwise to promote 27706f2543Smrg * the sale, use or other dealings in this Software without prior written 28706f2543Smrg * authorization from the copyright holder(s) and author(s). 29706f2543Smrg */ 30706f2543Smrg 31706f2543Smrg 32706f2543Smrg#ifdef HAVE_XORG_CONFIG_H 33706f2543Smrg#include <xorg-config.h> 34706f2543Smrg#endif 35706f2543Smrg 36706f2543Smrg#include "misc.h" 37706f2543Smrg#include "xf86.h" 38706f2543Smrg#include "xf86_OSproc.h" 39706f2543Smrg 40706f2543Smrg#include <X11/X.h> 41706f2543Smrg#include <X11/Xproto.h> 42706f2543Smrg#include "scrnintstr.h" 43706f2543Smrg#include "regionstr.h" 44706f2543Smrg#include "windowstr.h" 45706f2543Smrg#include "pixmapstr.h" 46706f2543Smrg#include "mivalidate.h" 47706f2543Smrg#include "validate.h" 48706f2543Smrg#include "resource.h" 49706f2543Smrg#include "gcstruct.h" 50706f2543Smrg#include "dixstruct.h" 51706f2543Smrg 52706f2543Smrg#include <X11/extensions/Xv.h> 53706f2543Smrg#include <X11/extensions/Xvproto.h> 54706f2543Smrg#include "xvdix.h" 55706f2543Smrg#include "xvmodproc.h" 56706f2543Smrg 57706f2543Smrg#include "xf86xvpriv.h" 58706f2543Smrg 59706f2543Smrg 60706f2543Smrg/* XvScreenRec fields */ 61706f2543Smrg 62706f2543Smrgstatic Bool xf86XVCloseScreen(int, ScreenPtr); 63706f2543Smrgstatic int xf86XVQueryAdaptors(ScreenPtr, XvAdaptorPtr *, int *); 64706f2543Smrg 65706f2543Smrg/* XvAdaptorRec fields */ 66706f2543Smrg 67706f2543Smrgstatic int xf86XVAllocatePort(unsigned long, XvPortPtr, XvPortPtr*); 68706f2543Smrgstatic int xf86XVFreePort(XvPortPtr); 69706f2543Smrgstatic int xf86XVPutVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, 70706f2543Smrg INT16, INT16, CARD16, CARD16, 71706f2543Smrg INT16, INT16, CARD16, CARD16); 72706f2543Smrgstatic int xf86XVPutStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, 73706f2543Smrg INT16, INT16, CARD16, CARD16, 74706f2543Smrg INT16, INT16, CARD16, CARD16); 75706f2543Smrgstatic int xf86XVGetVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, 76706f2543Smrg INT16, INT16, CARD16, CARD16, 77706f2543Smrg INT16, INT16, CARD16, CARD16); 78706f2543Smrgstatic int xf86XVGetStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, 79706f2543Smrg INT16, INT16, CARD16, CARD16, 80706f2543Smrg INT16, INT16, CARD16, CARD16); 81706f2543Smrgstatic int xf86XVStopVideo(ClientPtr, XvPortPtr, DrawablePtr); 82706f2543Smrgstatic int xf86XVSetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32); 83706f2543Smrgstatic int xf86XVGetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32*); 84706f2543Smrgstatic int xf86XVQueryBestSize(ClientPtr, XvPortPtr, CARD8, 85706f2543Smrg CARD16, CARD16,CARD16, CARD16, 86706f2543Smrg unsigned int*, unsigned int*); 87706f2543Smrgstatic int xf86XVPutImage(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, 88706f2543Smrg INT16, INT16, CARD16, CARD16, 89706f2543Smrg INT16, INT16, CARD16, CARD16, 90706f2543Smrg XvImagePtr, unsigned char*, Bool, 91706f2543Smrg CARD16, CARD16); 92706f2543Smrgstatic int xf86XVQueryImageAttributes(ClientPtr, XvPortPtr, XvImagePtr, 93706f2543Smrg CARD16*, CARD16*, int*, int*); 94706f2543Smrg 95706f2543Smrg 96706f2543Smrg/* ScreenRec fields */ 97706f2543Smrg 98706f2543Smrgstatic Bool xf86XVDestroyWindow(WindowPtr pWin); 99706f2543Smrgstatic void xf86XVWindowExposures(WindowPtr pWin, RegionPtr r1, RegionPtr r2); 100706f2543Smrgstatic void xf86XVPostValidateTree(WindowPtr pWin, WindowPtr pLayerWin, VTKind kind); 101706f2543Smrgstatic void xf86XVClipNotify(WindowPtr pWin, int dx, int dy); 102706f2543Smrg 103706f2543Smrg#define PostValidateTreeUndefined ((PostValidateTreeProcPtr)-1) 104706f2543Smrg 105706f2543Smrg/* ScrnInfoRec functions */ 106706f2543Smrg 107706f2543Smrgstatic Bool xf86XVEnterVT(int, int); 108706f2543Smrgstatic void xf86XVLeaveVT(int, int); 109706f2543Smrgstatic void xf86XVAdjustFrame(int index, int x, int y, int flags); 110706f2543Smrgstatic void xf86XVModeSet(ScrnInfoPtr pScrn); 111706f2543Smrg 112706f2543Smrg/* misc */ 113706f2543Smrg 114706f2543Smrgstatic Bool xf86XVInitAdaptors(ScreenPtr, XF86VideoAdaptorPtr*, int); 115706f2543Smrg 116706f2543Smrg 117706f2543Smrgstatic DevPrivateKeyRec XF86XVWindowKeyRec; 118706f2543Smrg#define XF86XVWindowKey (&XF86XVWindowKeyRec) 119706f2543Smrg 120706f2543SmrgDevPrivateKey XF86XvScreenKey; 121706f2543Smrg 122706f2543Smrgstatic unsigned long PortResource = 0; 123706f2543Smrg 124706f2543SmrgDevPrivateKey (*XvGetScreenKeyProc)(void) = NULL; 125706f2543Smrgunsigned long (*XvGetRTPortProc)(void) = NULL; 126706f2543Smrgint (*XvScreenInitProc)(ScreenPtr) = NULL; 127706f2543Smrg 128706f2543Smrg#define GET_XV_SCREEN(pScreen) \ 129706f2543Smrg ((XvScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, XF86XvScreenKey)) 130706f2543Smrg 131706f2543Smrg#define GET_XF86XV_SCREEN(pScreen) \ 132706f2543Smrg ((XF86XVScreenPtr)(GET_XV_SCREEN(pScreen)->devPriv.ptr)) 133706f2543Smrg 134706f2543Smrg#define GET_XF86XV_WINDOW(pWin) \ 135706f2543Smrg ((XF86XVWindowPtr)dixLookupPrivate(&(pWin)->devPrivates, XF86XVWindowKey)) 136706f2543Smrg 137706f2543Smrgstatic xf86XVInitGenericAdaptorPtr *GenDrivers = NULL; 138706f2543Smrgstatic int NumGenDrivers = 0; 139706f2543Smrg 140706f2543Smrgint 141706f2543Smrgxf86XVRegisterGenericAdaptorDriver( 142706f2543Smrg xf86XVInitGenericAdaptorPtr InitFunc 143706f2543Smrg){ 144706f2543Smrg xf86XVInitGenericAdaptorPtr *newdrivers; 145706f2543Smrg 146706f2543Smrg newdrivers = realloc(GenDrivers, sizeof(xf86XVInitGenericAdaptorPtr) * 147706f2543Smrg (1 + NumGenDrivers)); 148706f2543Smrg if (!newdrivers) 149706f2543Smrg return 0; 150706f2543Smrg GenDrivers = newdrivers; 151706f2543Smrg 152706f2543Smrg GenDrivers[NumGenDrivers++] = InitFunc; 153706f2543Smrg 154706f2543Smrg return 1; 155706f2543Smrg} 156706f2543Smrg 157706f2543Smrgint 158706f2543Smrgxf86XVListGenericAdaptors( 159706f2543Smrg ScrnInfoPtr pScrn, 160706f2543Smrg XF86VideoAdaptorPtr **adaptors 161706f2543Smrg){ 162706f2543Smrg int i,j,n,num; 163706f2543Smrg XF86VideoAdaptorPtr *DrivAdap,*new; 164706f2543Smrg 165706f2543Smrg num = 0; 166706f2543Smrg *adaptors = NULL; 167706f2543Smrg /* 168706f2543Smrg * The v4l driver registers itself first, but can use surfaces registered 169706f2543Smrg * by other drivers. So, call the v4l driver last. 170706f2543Smrg */ 171706f2543Smrg for (i = NumGenDrivers; --i >= 0; ) { 172706f2543Smrg DrivAdap = NULL; 173706f2543Smrg n = (*GenDrivers[i])(pScrn, &DrivAdap); 174706f2543Smrg if (0 == n) 175706f2543Smrg continue; 176706f2543Smrg new = realloc(*adaptors, sizeof(XF86VideoAdaptorPtr) * (num+n)); 177706f2543Smrg if (NULL == new) 178706f2543Smrg continue; 179706f2543Smrg *adaptors = new; 180706f2543Smrg for (j = 0; j < n; j++, num++) 181706f2543Smrg (*adaptors)[num] = DrivAdap[j]; 182706f2543Smrg } 183706f2543Smrg return num; 184706f2543Smrg} 185706f2543Smrg 186706f2543Smrg 187706f2543Smrg/**************** Offscreen surface stuff *******************/ 188706f2543Smrg 189706f2543Smrgtypedef struct { 190706f2543Smrg XF86OffscreenImagePtr images; 191706f2543Smrg int num; 192706f2543Smrg} OffscreenImageRec; 193706f2543Smrg 194706f2543Smrgstatic DevPrivateKeyRec OffscreenPrivateKeyRec; 195706f2543Smrg#define OffscreenPrivateKey (&OffscreenPrivateKeyRec) 196706f2543Smrg#define GetOffscreenImage(pScreen) ((OffscreenImageRec *) dixLookupPrivate(&(pScreen)->devPrivates, OffscreenPrivateKey)) 197706f2543Smrg 198706f2543SmrgBool 199706f2543Smrgxf86XVRegisterOffscreenImages( 200706f2543Smrg ScreenPtr pScreen, 201706f2543Smrg XF86OffscreenImagePtr images, 202706f2543Smrg int num 203706f2543Smrg){ 204706f2543Smrg OffscreenImageRec *OffscreenImage; 205706f2543Smrg /* This function may be called before xf86XVScreenInit, so there's 206706f2543Smrg * no better place than this to call dixRegisterPrivateKey to ensure we 207706f2543Smrg * have space reserved. After the first call it is a no-op. */ 208706f2543Smrg if(!dixRegisterPrivateKey(OffscreenPrivateKey, PRIVATE_SCREEN, sizeof(OffscreenImageRec)) || 209706f2543Smrg !(OffscreenImage = GetOffscreenImage(pScreen))) 210706f2543Smrg /* Every X.org driver assumes this function always succeeds, so 211706f2543Smrg * just die on allocation failure. */ 212706f2543Smrg FatalError("Could not allocate private storage for XV offscreen images.\n"); 213706f2543Smrg 214706f2543Smrg OffscreenImage->num = num; 215706f2543Smrg OffscreenImage->images = images; 216706f2543Smrg return TRUE; 217706f2543Smrg} 218706f2543Smrg 219706f2543SmrgXF86OffscreenImagePtr 220706f2543Smrgxf86XVQueryOffscreenImages( 221706f2543Smrg ScreenPtr pScreen, 222706f2543Smrg int *num 223706f2543Smrg){ 224706f2543Smrg OffscreenImageRec *OffscreenImage = GetOffscreenImage(pScreen); 225706f2543Smrg *num = OffscreenImage->num; 226706f2543Smrg return OffscreenImage->images; 227706f2543Smrg} 228706f2543Smrg 229706f2543Smrg 230706f2543SmrgXF86VideoAdaptorPtr 231706f2543Smrgxf86XVAllocateVideoAdaptorRec(ScrnInfoPtr pScrn) 232706f2543Smrg{ 233706f2543Smrg return calloc(1, sizeof(XF86VideoAdaptorRec)); 234706f2543Smrg} 235706f2543Smrg 236706f2543Smrgvoid 237706f2543Smrgxf86XVFreeVideoAdaptorRec(XF86VideoAdaptorPtr ptr) 238706f2543Smrg{ 239706f2543Smrg free(ptr); 240706f2543Smrg} 241706f2543Smrg 242706f2543Smrg 243706f2543SmrgBool 244706f2543Smrgxf86XVScreenInit( 245706f2543Smrg ScreenPtr pScreen, 246706f2543Smrg XF86VideoAdaptorPtr *adaptors, 247706f2543Smrg int num 248706f2543Smrg){ 249706f2543Smrg ScrnInfoPtr pScrn; 250706f2543Smrg XF86XVScreenPtr ScreenPriv; 251706f2543Smrg XvScreenPtr pxvs; 252706f2543Smrg 253706f2543Smrg if(num <= 0 || 254706f2543Smrg !XvGetScreenKeyProc || !XvGetRTPortProc || !XvScreenInitProc) 255706f2543Smrg return FALSE; 256706f2543Smrg 257706f2543Smrg if(Success != (*XvScreenInitProc)(pScreen)) return FALSE; 258706f2543Smrg 259706f2543Smrg if (!dixRegisterPrivateKey(&XF86XVWindowKeyRec, PRIVATE_WINDOW, 0)) 260706f2543Smrg return FALSE; 261706f2543Smrg 262706f2543Smrg XF86XvScreenKey = (*XvGetScreenKeyProc)(); 263706f2543Smrg 264706f2543Smrg PortResource = (*XvGetRTPortProc)(); 265706f2543Smrg 266706f2543Smrg pxvs = GET_XV_SCREEN(pScreen); 267706f2543Smrg 268706f2543Smrg /* Anyone initializing the Xv layer must provide these two. 269706f2543Smrg The Xv di layer calls them without even checking if they exist! */ 270706f2543Smrg 271706f2543Smrg pxvs->ddCloseScreen = xf86XVCloseScreen; 272706f2543Smrg pxvs->ddQueryAdaptors = xf86XVQueryAdaptors; 273706f2543Smrg 274706f2543Smrg /* The Xv di layer provides us with a private hook so that we don't 275706f2543Smrg have to allocate our own screen private. They also provide 276706f2543Smrg a CloseScreen hook so that we don't have to wrap it. I'm not 277706f2543Smrg sure that I appreciate that. */ 278706f2543Smrg 279706f2543Smrg ScreenPriv = malloc(sizeof(XF86XVScreenRec)); 280706f2543Smrg pxvs->devPriv.ptr = (pointer)ScreenPriv; 281706f2543Smrg 282706f2543Smrg if(!ScreenPriv) return FALSE; 283706f2543Smrg 284706f2543Smrg pScrn = xf86Screens[pScreen->myNum]; 285706f2543Smrg 286706f2543Smrg ScreenPriv->DestroyWindow = pScreen->DestroyWindow; 287706f2543Smrg ScreenPriv->WindowExposures = pScreen->WindowExposures; 288706f2543Smrg ScreenPriv->PostValidateTree = PostValidateTreeUndefined; 289706f2543Smrg ScreenPriv->ClipNotify = pScreen->ClipNotify; 290706f2543Smrg ScreenPriv->EnterVT = pScrn->EnterVT; 291706f2543Smrg ScreenPriv->LeaveVT = pScrn->LeaveVT; 292706f2543Smrg ScreenPriv->AdjustFrame = pScrn->AdjustFrame; 293706f2543Smrg ScreenPriv->ModeSet = pScrn->ModeSet; 294706f2543Smrg 295706f2543Smrg pScreen->DestroyWindow = xf86XVDestroyWindow; 296706f2543Smrg pScreen->WindowExposures = xf86XVWindowExposures; 297706f2543Smrg pScreen->ClipNotify = xf86XVClipNotify; 298706f2543Smrg pScrn->EnterVT = xf86XVEnterVT; 299706f2543Smrg pScrn->LeaveVT = xf86XVLeaveVT; 300706f2543Smrg if(pScrn->AdjustFrame) 301706f2543Smrg pScrn->AdjustFrame = xf86XVAdjustFrame; 302706f2543Smrg pScrn->ModeSet = xf86XVModeSet; 303706f2543Smrg 304706f2543Smrg if(!xf86XVInitAdaptors(pScreen, adaptors, num)) 305706f2543Smrg return FALSE; 306706f2543Smrg 307706f2543Smrg return TRUE; 308706f2543Smrg} 309706f2543Smrg 310706f2543Smrgstatic void 311706f2543Smrgxf86XVFreeAdaptor(XvAdaptorPtr pAdaptor) 312706f2543Smrg{ 313706f2543Smrg int i; 314706f2543Smrg 315706f2543Smrg free(pAdaptor->name); 316706f2543Smrg 317706f2543Smrg if(pAdaptor->pEncodings) { 318706f2543Smrg XvEncodingPtr pEncode = pAdaptor->pEncodings; 319706f2543Smrg 320706f2543Smrg for(i = 0; i < pAdaptor->nEncodings; i++, pEncode++) 321706f2543Smrg free(pEncode->name); 322706f2543Smrg free(pAdaptor->pEncodings); 323706f2543Smrg } 324706f2543Smrg 325706f2543Smrg free(pAdaptor->pFormats); 326706f2543Smrg 327706f2543Smrg if(pAdaptor->pPorts) { 328706f2543Smrg XvPortPtr pPort = pAdaptor->pPorts; 329706f2543Smrg XvPortRecPrivatePtr pPriv; 330706f2543Smrg 331706f2543Smrg for(i = 0; i < pAdaptor->nPorts; i++, pPort++) { 332706f2543Smrg pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr; 333706f2543Smrg if(pPriv) { 334706f2543Smrg if(pPriv->clientClip) 335706f2543Smrg RegionDestroy(pPriv->clientClip); 336706f2543Smrg if(pPriv->pCompositeClip && pPriv->FreeCompositeClip) 337706f2543Smrg RegionDestroy(pPriv->pCompositeClip); 338706f2543Smrg if (pPriv->ckeyFilled) 339706f2543Smrg RegionDestroy(pPriv->ckeyFilled); 340706f2543Smrg free(pPriv); 341706f2543Smrg } 342706f2543Smrg } 343706f2543Smrg free(pAdaptor->pPorts); 344706f2543Smrg } 345706f2543Smrg 346706f2543Smrg if(pAdaptor->nAttributes) { 347706f2543Smrg XvAttributePtr pAttribute = pAdaptor->pAttributes; 348706f2543Smrg 349706f2543Smrg for(i = 0; i < pAdaptor->nAttributes; i++, pAttribute++) 350706f2543Smrg free(pAttribute->name); 351706f2543Smrg free(pAdaptor->pAttributes); 352706f2543Smrg } 353706f2543Smrg 354706f2543Smrg free(pAdaptor->pImages); 355706f2543Smrg free(pAdaptor->devPriv.ptr); 356706f2543Smrg} 357706f2543Smrg 358706f2543Smrgstatic Bool 359706f2543Smrgxf86XVInitAdaptors( 360706f2543Smrg ScreenPtr pScreen, 361706f2543Smrg XF86VideoAdaptorPtr *infoPtr, 362706f2543Smrg int number 363706f2543Smrg) { 364706f2543Smrg XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); 365706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 366706f2543Smrg XF86VideoAdaptorPtr adaptorPtr; 367706f2543Smrg XvAdaptorPtr pAdaptor, pa; 368706f2543Smrg XvAdaptorRecPrivatePtr adaptorPriv; 369706f2543Smrg int na, numAdaptor; 370706f2543Smrg XvPortRecPrivatePtr portPriv; 371706f2543Smrg XvPortPtr pPort, pp; 372706f2543Smrg int numPort; 373706f2543Smrg XF86AttributePtr attributePtr; 374706f2543Smrg XvAttributePtr pAttribute, pat; 375706f2543Smrg XF86VideoFormatPtr formatPtr; 376706f2543Smrg XvFormatPtr pFormat, pf; 377706f2543Smrg int numFormat, totFormat; 378706f2543Smrg XF86VideoEncodingPtr encodingPtr; 379706f2543Smrg XvEncodingPtr pEncode, pe; 380706f2543Smrg XF86ImagePtr imagePtr; 381706f2543Smrg XvImagePtr pImage, pi; 382706f2543Smrg int numVisuals; 383706f2543Smrg VisualPtr pVisual; 384706f2543Smrg int i; 385706f2543Smrg 386706f2543Smrg pxvs->nAdaptors = 0; 387706f2543Smrg pxvs->pAdaptors = NULL; 388706f2543Smrg 389706f2543Smrg if(!(pAdaptor = calloc(number, sizeof(XvAdaptorRec)))) 390706f2543Smrg return FALSE; 391706f2543Smrg 392706f2543Smrg for(pa = pAdaptor, na = 0, numAdaptor = 0; na < number; na++, adaptorPtr++) { 393706f2543Smrg adaptorPtr = infoPtr[na]; 394706f2543Smrg 395706f2543Smrg if(!adaptorPtr->StopVideo || !adaptorPtr->SetPortAttribute || 396706f2543Smrg !adaptorPtr->GetPortAttribute || !adaptorPtr->QueryBestSize) 397706f2543Smrg continue; 398706f2543Smrg 399706f2543Smrg /* client libs expect at least one encoding */ 400706f2543Smrg if(!adaptorPtr->nEncodings || !adaptorPtr->pEncodings) 401706f2543Smrg continue; 402706f2543Smrg 403706f2543Smrg pa->type = adaptorPtr->type; 404706f2543Smrg 405706f2543Smrg if(!adaptorPtr->PutVideo && !adaptorPtr->GetVideo) 406706f2543Smrg pa->type &= ~XvVideoMask; 407706f2543Smrg 408706f2543Smrg if(!adaptorPtr->PutStill && !adaptorPtr->GetStill) 409706f2543Smrg pa->type &= ~XvStillMask; 410706f2543Smrg 411706f2543Smrg if(!adaptorPtr->PutImage || !adaptorPtr->QueryImageAttributes) 412706f2543Smrg pa->type &= ~XvImageMask; 413706f2543Smrg 414706f2543Smrg if(!adaptorPtr->PutVideo && !adaptorPtr->PutImage && 415706f2543Smrg !adaptorPtr->PutStill) 416706f2543Smrg pa->type &= ~XvInputMask; 417706f2543Smrg 418706f2543Smrg if(!adaptorPtr->GetVideo && !adaptorPtr->GetStill) 419706f2543Smrg pa->type &= ~XvOutputMask; 420706f2543Smrg 421706f2543Smrg if(!(adaptorPtr->type & (XvPixmapMask | XvWindowMask))) 422706f2543Smrg continue; 423706f2543Smrg if(!(adaptorPtr->type & (XvImageMask | XvVideoMask | XvStillMask))) 424706f2543Smrg continue; 425706f2543Smrg 426706f2543Smrg pa->pScreen = pScreen; 427706f2543Smrg pa->ddAllocatePort = xf86XVAllocatePort; 428706f2543Smrg pa->ddFreePort = xf86XVFreePort; 429706f2543Smrg pa->ddPutVideo = xf86XVPutVideo; 430706f2543Smrg pa->ddPutStill = xf86XVPutStill; 431706f2543Smrg pa->ddGetVideo = xf86XVGetVideo; 432706f2543Smrg pa->ddGetStill = xf86XVGetStill; 433706f2543Smrg pa->ddStopVideo = xf86XVStopVideo; 434706f2543Smrg pa->ddPutImage = xf86XVPutImage; 435706f2543Smrg pa->ddSetPortAttribute = xf86XVSetPortAttribute; 436706f2543Smrg pa->ddGetPortAttribute = xf86XVGetPortAttribute; 437706f2543Smrg pa->ddQueryBestSize = xf86XVQueryBestSize; 438706f2543Smrg pa->ddQueryImageAttributes = xf86XVQueryImageAttributes; 439706f2543Smrg pa->name = strdup(adaptorPtr->name); 440706f2543Smrg 441706f2543Smrg if(adaptorPtr->nEncodings && 442706f2543Smrg (pEncode = calloc(adaptorPtr->nEncodings, sizeof(XvEncodingRec)))) { 443706f2543Smrg 444706f2543Smrg for(pe = pEncode, encodingPtr = adaptorPtr->pEncodings, i = 0; 445706f2543Smrg i < adaptorPtr->nEncodings; pe++, i++, encodingPtr++) 446706f2543Smrg { 447706f2543Smrg pe->id = encodingPtr->id; 448706f2543Smrg pe->pScreen = pScreen; 449706f2543Smrg pe->name = strdup(encodingPtr->name); 450706f2543Smrg pe->width = encodingPtr->width; 451706f2543Smrg pe->height = encodingPtr->height; 452706f2543Smrg pe->rate.numerator = encodingPtr->rate.numerator; 453706f2543Smrg pe->rate.denominator = encodingPtr->rate.denominator; 454706f2543Smrg } 455706f2543Smrg pa->nEncodings = adaptorPtr->nEncodings; 456706f2543Smrg pa->pEncodings = pEncode; 457706f2543Smrg } 458706f2543Smrg 459706f2543Smrg if(adaptorPtr->nImages && 460706f2543Smrg (pImage = calloc(adaptorPtr->nImages, sizeof(XvImageRec)))) { 461706f2543Smrg 462706f2543Smrg for(i = 0, pi = pImage, imagePtr = adaptorPtr->pImages; 463706f2543Smrg i < adaptorPtr->nImages; i++, pi++, imagePtr++) 464706f2543Smrg { 465706f2543Smrg pi->id = imagePtr->id; 466706f2543Smrg pi->type = imagePtr->type; 467706f2543Smrg pi->byte_order = imagePtr->byte_order; 468706f2543Smrg memcpy(pi->guid, imagePtr->guid, 16); 469706f2543Smrg pi->bits_per_pixel = imagePtr->bits_per_pixel; 470706f2543Smrg pi->format = imagePtr->format; 471706f2543Smrg pi->num_planes = imagePtr->num_planes; 472706f2543Smrg pi->depth = imagePtr->depth; 473706f2543Smrg pi->red_mask = imagePtr->red_mask; 474706f2543Smrg pi->green_mask = imagePtr->green_mask; 475706f2543Smrg pi->blue_mask = imagePtr->blue_mask; 476706f2543Smrg pi->y_sample_bits = imagePtr->y_sample_bits; 477706f2543Smrg pi->u_sample_bits = imagePtr->u_sample_bits; 478706f2543Smrg pi->v_sample_bits = imagePtr->v_sample_bits; 479706f2543Smrg pi->horz_y_period = imagePtr->horz_y_period; 480706f2543Smrg pi->horz_u_period = imagePtr->horz_u_period; 481706f2543Smrg pi->horz_v_period = imagePtr->horz_v_period; 482706f2543Smrg pi->vert_y_period = imagePtr->vert_y_period; 483706f2543Smrg pi->vert_u_period = imagePtr->vert_u_period; 484706f2543Smrg pi->vert_v_period = imagePtr->vert_v_period; 485706f2543Smrg memcpy(pi->component_order, imagePtr->component_order, 32); 486706f2543Smrg pi->scanline_order = imagePtr->scanline_order; 487706f2543Smrg } 488706f2543Smrg pa->nImages = adaptorPtr->nImages; 489706f2543Smrg pa->pImages = pImage; 490706f2543Smrg } 491706f2543Smrg 492706f2543Smrg if(adaptorPtr->nAttributes && 493706f2543Smrg (pAttribute = calloc(adaptorPtr->nAttributes, sizeof(XvAttributeRec)))) 494706f2543Smrg { 495706f2543Smrg for(pat = pAttribute, attributePtr = adaptorPtr->pAttributes, i = 0; 496706f2543Smrg i < adaptorPtr->nAttributes; pat++, i++, attributePtr++) 497706f2543Smrg { 498706f2543Smrg pat->flags = attributePtr->flags; 499706f2543Smrg pat->min_value = attributePtr->min_value; 500706f2543Smrg pat->max_value = attributePtr->max_value; 501706f2543Smrg pat->name = strdup(attributePtr->name); 502706f2543Smrg } 503706f2543Smrg pa->nAttributes = adaptorPtr->nAttributes; 504706f2543Smrg pa->pAttributes = pAttribute; 505706f2543Smrg } 506706f2543Smrg 507706f2543Smrg 508706f2543Smrg totFormat = adaptorPtr->nFormats; 509706f2543Smrg 510706f2543Smrg if(!(pFormat = calloc(totFormat, sizeof(XvFormatRec)))) { 511706f2543Smrg xf86XVFreeAdaptor(pa); 512706f2543Smrg continue; 513706f2543Smrg } 514706f2543Smrg for(pf = pFormat, i = 0, numFormat = 0, formatPtr = adaptorPtr->pFormats; 515706f2543Smrg i < adaptorPtr->nFormats; i++, formatPtr++) 516706f2543Smrg { 517706f2543Smrg numVisuals = pScreen->numVisuals; 518706f2543Smrg pVisual = pScreen->visuals; 519706f2543Smrg 520706f2543Smrg while(numVisuals--) { 521706f2543Smrg if((pVisual->class == formatPtr->class) && 522706f2543Smrg (pVisual->nplanes == formatPtr->depth)) { 523706f2543Smrg 524706f2543Smrg if(numFormat >= totFormat) { 525706f2543Smrg void *moreSpace; 526706f2543Smrg totFormat *= 2; 527706f2543Smrg moreSpace = realloc(pFormat, 528706f2543Smrg totFormat * sizeof(XvFormatRec)); 529706f2543Smrg if(!moreSpace) break; 530706f2543Smrg pFormat = moreSpace; 531706f2543Smrg pf = pFormat + numFormat; 532706f2543Smrg } 533706f2543Smrg 534706f2543Smrg pf->visual = pVisual->vid; 535706f2543Smrg pf->depth = formatPtr->depth; 536706f2543Smrg 537706f2543Smrg pf++; 538706f2543Smrg numFormat++; 539706f2543Smrg } 540706f2543Smrg pVisual++; 541706f2543Smrg } 542706f2543Smrg } 543706f2543Smrg pa->nFormats = numFormat; 544706f2543Smrg pa->pFormats = pFormat; 545706f2543Smrg if(!numFormat) { 546706f2543Smrg xf86XVFreeAdaptor(pa); 547706f2543Smrg continue; 548706f2543Smrg } 549706f2543Smrg 550706f2543Smrg if(!(adaptorPriv = calloc(1, sizeof(XvAdaptorRecPrivate)))) { 551706f2543Smrg xf86XVFreeAdaptor(pa); 552706f2543Smrg continue; 553706f2543Smrg } 554706f2543Smrg 555706f2543Smrg adaptorPriv->flags = adaptorPtr->flags; 556706f2543Smrg adaptorPriv->PutVideo = adaptorPtr->PutVideo; 557706f2543Smrg adaptorPriv->PutStill = adaptorPtr->PutStill; 558706f2543Smrg adaptorPriv->GetVideo = adaptorPtr->GetVideo; 559706f2543Smrg adaptorPriv->GetStill = adaptorPtr->GetStill; 560706f2543Smrg adaptorPriv->StopVideo = adaptorPtr->StopVideo; 561706f2543Smrg adaptorPriv->SetPortAttribute = adaptorPtr->SetPortAttribute; 562706f2543Smrg adaptorPriv->GetPortAttribute = adaptorPtr->GetPortAttribute; 563706f2543Smrg adaptorPriv->QueryBestSize = adaptorPtr->QueryBestSize; 564706f2543Smrg adaptorPriv->QueryImageAttributes = adaptorPtr->QueryImageAttributes; 565706f2543Smrg adaptorPriv->PutImage = adaptorPtr->PutImage; 566706f2543Smrg adaptorPriv->ReputImage = adaptorPtr->ReputImage; /* image/still */ 567706f2543Smrg 568706f2543Smrg pa->devPriv.ptr = (pointer)adaptorPriv; 569706f2543Smrg 570706f2543Smrg if(!(pPort = calloc(adaptorPtr->nPorts, sizeof(XvPortRec)))) { 571706f2543Smrg xf86XVFreeAdaptor(pa); 572706f2543Smrg continue; 573706f2543Smrg } 574706f2543Smrg for(pp = pPort, i = 0, numPort = 0; 575706f2543Smrg i < adaptorPtr->nPorts; i++) { 576706f2543Smrg 577706f2543Smrg if(!(pp->id = FakeClientID(0))) 578706f2543Smrg continue; 579706f2543Smrg 580706f2543Smrg if(!(portPriv = calloc(1, sizeof(XvPortRecPrivate)))) 581706f2543Smrg continue; 582706f2543Smrg 583706f2543Smrg if(!AddResource(pp->id, PortResource, pp)) { 584706f2543Smrg free(portPriv); 585706f2543Smrg continue; 586706f2543Smrg } 587706f2543Smrg 588706f2543Smrg pp->pAdaptor = pa; 589706f2543Smrg pp->pNotify = (XvPortNotifyPtr)NULL; 590706f2543Smrg pp->pDraw = (DrawablePtr)NULL; 591706f2543Smrg pp->client = (ClientPtr)NULL; 592706f2543Smrg pp->grab.client = (ClientPtr)NULL; 593706f2543Smrg pp->time = currentTime; 594706f2543Smrg pp->devPriv.ptr = portPriv; 595706f2543Smrg 596706f2543Smrg portPriv->pScrn = pScrn; 597706f2543Smrg portPriv->AdaptorRec = adaptorPriv; 598706f2543Smrg portPriv->DevPriv.ptr = adaptorPtr->pPortPrivates[i].ptr; 599706f2543Smrg 600706f2543Smrg pp++; 601706f2543Smrg numPort++; 602706f2543Smrg } 603706f2543Smrg pa->nPorts = numPort; 604706f2543Smrg pa->pPorts = pPort; 605706f2543Smrg if(!numPort) { 606706f2543Smrg xf86XVFreeAdaptor(pa); 607706f2543Smrg continue; 608706f2543Smrg } 609706f2543Smrg 610706f2543Smrg pa->base_id = pPort->id; 611706f2543Smrg 612706f2543Smrg pa++; 613706f2543Smrg numAdaptor++; 614706f2543Smrg } 615706f2543Smrg 616706f2543Smrg if(numAdaptor) { 617706f2543Smrg pxvs->nAdaptors = numAdaptor; 618706f2543Smrg pxvs->pAdaptors = pAdaptor; 619706f2543Smrg } else { 620706f2543Smrg free(pAdaptor); 621706f2543Smrg return FALSE; 622706f2543Smrg } 623706f2543Smrg 624706f2543Smrg return TRUE; 625706f2543Smrg} 626706f2543Smrg 627706f2543Smrg/* Video should be clipped to the intersection of the window cliplist 628706f2543Smrg and the client cliplist specified in the GC for which the video was 629706f2543Smrg initialized. When we need to reclip a window, the GC that started 630706f2543Smrg the video may not even be around anymore. That's why we save the 631706f2543Smrg client clip from the GC when the video is initialized. We then 632706f2543Smrg use xf86XVUpdateCompositeClip to calculate the new composite clip 633706f2543Smrg when we need it. This is different from what DEC did. They saved 634706f2543Smrg the GC and used it's clip list when they needed to reclip the window, 635706f2543Smrg even if the client clip was different from the one the video was 636706f2543Smrg initialized with. If the original GC was destroyed, they had to stop 637706f2543Smrg the video. I like the new method better (MArk). 638706f2543Smrg 639706f2543Smrg This function only works for windows. Will need to rewrite when 640706f2543Smrg (if) we support pixmap rendering. 641706f2543Smrg*/ 642706f2543Smrg 643706f2543Smrgstatic void 644706f2543Smrgxf86XVUpdateCompositeClip(XvPortRecPrivatePtr portPriv) 645706f2543Smrg{ 646706f2543Smrg RegionPtr pregWin, pCompositeClip; 647706f2543Smrg WindowPtr pWin; 648706f2543Smrg Bool freeCompClip = FALSE; 649706f2543Smrg 650706f2543Smrg if(portPriv->pCompositeClip) 651706f2543Smrg return; 652706f2543Smrg 653706f2543Smrg pWin = (WindowPtr)portPriv->pDraw; 654706f2543Smrg 655706f2543Smrg /* get window clip list */ 656706f2543Smrg if(portPriv->subWindowMode == IncludeInferiors) { 657706f2543Smrg pregWin = NotClippedByChildren(pWin); 658706f2543Smrg freeCompClip = TRUE; 659706f2543Smrg } else 660706f2543Smrg pregWin = &pWin->clipList; 661706f2543Smrg 662706f2543Smrg if(!portPriv->clientClip) { 663706f2543Smrg portPriv->pCompositeClip = pregWin; 664706f2543Smrg portPriv->FreeCompositeClip = freeCompClip; 665706f2543Smrg return; 666706f2543Smrg } 667706f2543Smrg 668706f2543Smrg pCompositeClip = RegionCreate(NullBox, 1); 669706f2543Smrg RegionCopy(pCompositeClip, portPriv->clientClip); 670706f2543Smrg RegionTranslate(pCompositeClip, 671706f2543Smrg portPriv->pDraw->x, portPriv->pDraw->y); 672706f2543Smrg RegionIntersect(pCompositeClip, pregWin, pCompositeClip); 673706f2543Smrg 674706f2543Smrg portPriv->pCompositeClip = pCompositeClip; 675706f2543Smrg portPriv->FreeCompositeClip = TRUE; 676706f2543Smrg 677706f2543Smrg if(freeCompClip) { 678706f2543Smrg RegionDestroy(pregWin); 679706f2543Smrg } 680706f2543Smrg} 681706f2543Smrg 682706f2543Smrg/* Save the current clientClip and update the CompositeClip whenever 683706f2543Smrg we have a fresh GC */ 684706f2543Smrg 685706f2543Smrgstatic void 686706f2543Smrgxf86XVCopyClip( 687706f2543Smrg XvPortRecPrivatePtr portPriv, 688706f2543Smrg GCPtr pGC 689706f2543Smrg){ 690706f2543Smrg /* copy the new clip if it exists */ 691706f2543Smrg if((pGC->clientClipType == CT_REGION) && pGC->clientClip) { 692706f2543Smrg if(!portPriv->clientClip) 693706f2543Smrg portPriv->clientClip = RegionCreate(NullBox, 1); 694706f2543Smrg /* Note: this is in window coordinates */ 695706f2543Smrg RegionCopy(portPriv->clientClip, pGC->clientClip); 696706f2543Smrg RegionTranslate(portPriv->clientClip, 697706f2543Smrg pGC->clipOrg.x, pGC->clipOrg.y); 698706f2543Smrg } else if(portPriv->clientClip) { /* free the old clientClip */ 699706f2543Smrg RegionDestroy(portPriv->clientClip); 700706f2543Smrg portPriv->clientClip = NULL; 701706f2543Smrg } 702706f2543Smrg 703706f2543Smrg /* get rid of the old clip list */ 704706f2543Smrg if(portPriv->pCompositeClip && portPriv->FreeCompositeClip) { 705706f2543Smrg RegionDestroy(portPriv->pCompositeClip); 706706f2543Smrg } 707706f2543Smrg 708706f2543Smrg portPriv->pCompositeClip = pGC->pCompositeClip; 709706f2543Smrg portPriv->FreeCompositeClip = FALSE; 710706f2543Smrg portPriv->subWindowMode = pGC->subWindowMode; 711706f2543Smrg} 712706f2543Smrg 713706f2543Smrgstatic void 714706f2543Smrgxf86XVCopyCompositeClip(XvPortRecPrivatePtr portPriv, 715706f2543Smrg GCPtr pGC, 716706f2543Smrg DrawablePtr pDraw) 717706f2543Smrg{ 718706f2543Smrg if (!portPriv->clientClip) 719706f2543Smrg portPriv->clientClip = RegionCreate(NullBox, 1); 720706f2543Smrg /* Keep the original GC composite clip around for ReputImage */ 721706f2543Smrg RegionCopy(portPriv->clientClip, pGC->pCompositeClip); 722706f2543Smrg RegionTranslate(portPriv->clientClip, 723706f2543Smrg -pDraw->x, -pDraw->y); 724706f2543Smrg 725706f2543Smrg /* get rid of the old clip list */ 726706f2543Smrg if (portPriv->pCompositeClip && portPriv->FreeCompositeClip) 727706f2543Smrg RegionDestroy(portPriv->pCompositeClip); 728706f2543Smrg 729706f2543Smrg portPriv->pCompositeClip = pGC->pCompositeClip; 730706f2543Smrg portPriv->FreeCompositeClip = FALSE; 731706f2543Smrg portPriv->subWindowMode = pGC->subWindowMode; 732706f2543Smrg} 733706f2543Smrg 734706f2543Smrgstatic int 735706f2543Smrgxf86XVRegetVideo(XvPortRecPrivatePtr portPriv) 736706f2543Smrg{ 737706f2543Smrg RegionRec WinRegion; 738706f2543Smrg RegionRec ClipRegion; 739706f2543Smrg BoxRec WinBox; 740706f2543Smrg int ret = Success; 741706f2543Smrg Bool clippedAway = FALSE; 742706f2543Smrg 743706f2543Smrg xf86XVUpdateCompositeClip(portPriv); 744706f2543Smrg 745706f2543Smrg /* translate the video region to the screen */ 746706f2543Smrg WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x; 747706f2543Smrg WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y; 748706f2543Smrg WinBox.x2 = WinBox.x1 + portPriv->drw_w; 749706f2543Smrg WinBox.y2 = WinBox.y1 + portPriv->drw_h; 750706f2543Smrg 751706f2543Smrg /* clip to the window composite clip */ 752706f2543Smrg RegionInit(&WinRegion, &WinBox, 1); 753706f2543Smrg RegionNull(&ClipRegion); 754706f2543Smrg RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip); 755706f2543Smrg 756706f2543Smrg /* that's all if it's totally obscured */ 757706f2543Smrg if(!RegionNotEmpty(&ClipRegion)) { 758706f2543Smrg clippedAway = TRUE; 759706f2543Smrg goto CLIP_VIDEO_BAILOUT; 760706f2543Smrg } 761706f2543Smrg 762706f2543Smrg if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { 763706f2543Smrg RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion); 764706f2543Smrg } 765706f2543Smrg 766706f2543Smrg ret = (*portPriv->AdaptorRec->GetVideo)(portPriv->pScrn, 767706f2543Smrg portPriv->vid_x, portPriv->vid_y, 768706f2543Smrg WinBox.x1, WinBox.y1, 769706f2543Smrg portPriv->vid_w, portPriv->vid_h, 770706f2543Smrg portPriv->drw_w, portPriv->drw_h, 771706f2543Smrg &ClipRegion, portPriv->DevPriv.ptr, 772706f2543Smrg portPriv->pDraw); 773706f2543Smrg 774706f2543Smrg if(ret == Success) 775706f2543Smrg portPriv->isOn = XV_ON; 776706f2543Smrg 777706f2543SmrgCLIP_VIDEO_BAILOUT: 778706f2543Smrg 779706f2543Smrg if((clippedAway || (ret != Success)) && portPriv->isOn == XV_ON) { 780706f2543Smrg (*portPriv->AdaptorRec->StopVideo)( 781706f2543Smrg portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); 782706f2543Smrg portPriv->isOn = XV_PENDING; 783706f2543Smrg } 784706f2543Smrg 785706f2543Smrg /* This clip was copied and only good for one shot */ 786706f2543Smrg if(!portPriv->FreeCompositeClip) 787706f2543Smrg portPriv->pCompositeClip = NULL; 788706f2543Smrg 789706f2543Smrg RegionUninit(&WinRegion); 790706f2543Smrg RegionUninit(&ClipRegion); 791706f2543Smrg 792706f2543Smrg return ret; 793706f2543Smrg} 794706f2543Smrg 795706f2543Smrg 796706f2543Smrgstatic int 797706f2543Smrgxf86XVReputVideo(XvPortRecPrivatePtr portPriv) 798706f2543Smrg{ 799706f2543Smrg RegionRec WinRegion; 800706f2543Smrg RegionRec ClipRegion; 801706f2543Smrg BoxRec WinBox; 802706f2543Smrg int ret = Success; 803706f2543Smrg Bool clippedAway = FALSE; 804706f2543Smrg 805706f2543Smrg xf86XVUpdateCompositeClip(portPriv); 806706f2543Smrg 807706f2543Smrg /* translate the video region to the screen */ 808706f2543Smrg WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x; 809706f2543Smrg WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y; 810706f2543Smrg WinBox.x2 = WinBox.x1 + portPriv->drw_w; 811706f2543Smrg WinBox.y2 = WinBox.y1 + portPriv->drw_h; 812706f2543Smrg 813706f2543Smrg /* clip to the window composite clip */ 814706f2543Smrg RegionInit(&WinRegion, &WinBox, 1); 815706f2543Smrg RegionNull(&ClipRegion); 816706f2543Smrg RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip); 817706f2543Smrg 818706f2543Smrg /* clip and translate to the viewport */ 819706f2543Smrg if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { 820706f2543Smrg RegionRec VPReg; 821706f2543Smrg BoxRec VPBox; 822706f2543Smrg 823706f2543Smrg VPBox.x1 = portPriv->pScrn->frameX0; 824706f2543Smrg VPBox.y1 = portPriv->pScrn->frameY0; 825706f2543Smrg VPBox.x2 = portPriv->pScrn->frameX1 + 1; 826706f2543Smrg VPBox.y2 = portPriv->pScrn->frameY1 + 1; 827706f2543Smrg 828706f2543Smrg RegionInit(&VPReg, &VPBox, 1); 829706f2543Smrg RegionIntersect(&ClipRegion, &ClipRegion, &VPReg); 830706f2543Smrg RegionUninit(&VPReg); 831706f2543Smrg } 832706f2543Smrg 833706f2543Smrg /* that's all if it's totally obscured */ 834706f2543Smrg if(!RegionNotEmpty(&ClipRegion)) { 835706f2543Smrg clippedAway = TRUE; 836706f2543Smrg goto CLIP_VIDEO_BAILOUT; 837706f2543Smrg } 838706f2543Smrg 839706f2543Smrg /* bailout if we have to clip but the hardware doesn't support it */ 840706f2543Smrg if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) { 841706f2543Smrg BoxPtr clipBox = RegionRects(&ClipRegion); 842706f2543Smrg if( (RegionNumRects(&ClipRegion) != 1) || 843706f2543Smrg (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) || 844706f2543Smrg (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) 845706f2543Smrg { 846706f2543Smrg clippedAway = TRUE; 847706f2543Smrg goto CLIP_VIDEO_BAILOUT; 848706f2543Smrg } 849706f2543Smrg } 850706f2543Smrg 851706f2543Smrg if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { 852706f2543Smrg RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion); 853706f2543Smrg } 854706f2543Smrg 855706f2543Smrg ret = (*portPriv->AdaptorRec->PutVideo)(portPriv->pScrn, 856706f2543Smrg portPriv->vid_x, portPriv->vid_y, 857706f2543Smrg WinBox.x1, WinBox.y1, 858706f2543Smrg portPriv->vid_w, portPriv->vid_h, 859706f2543Smrg portPriv->drw_w, portPriv->drw_h, 860706f2543Smrg &ClipRegion, portPriv->DevPriv.ptr, 861706f2543Smrg portPriv->pDraw); 862706f2543Smrg 863706f2543Smrg if(ret == Success) portPriv->isOn = XV_ON; 864706f2543Smrg 865706f2543SmrgCLIP_VIDEO_BAILOUT: 866706f2543Smrg 867706f2543Smrg if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { 868706f2543Smrg (*portPriv->AdaptorRec->StopVideo)( 869706f2543Smrg portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); 870706f2543Smrg portPriv->isOn = XV_PENDING; 871706f2543Smrg } 872706f2543Smrg 873706f2543Smrg /* This clip was copied and only good for one shot */ 874706f2543Smrg if(!portPriv->FreeCompositeClip) 875706f2543Smrg portPriv->pCompositeClip = NULL; 876706f2543Smrg 877706f2543Smrg RegionUninit(&WinRegion); 878706f2543Smrg RegionUninit(&ClipRegion); 879706f2543Smrg 880706f2543Smrg return ret; 881706f2543Smrg} 882706f2543Smrg 883706f2543Smrg/* Reput image/still */ 884706f2543Smrgstatic int 885706f2543Smrgxf86XVReputImage(XvPortRecPrivatePtr portPriv) 886706f2543Smrg{ 887706f2543Smrg RegionRec WinRegion; 888706f2543Smrg RegionRec ClipRegion; 889706f2543Smrg BoxRec WinBox; 890706f2543Smrg int ret = Success; 891706f2543Smrg Bool clippedAway = FALSE; 892706f2543Smrg 893706f2543Smrg xf86XVUpdateCompositeClip(portPriv); 894706f2543Smrg 895706f2543Smrg /* the clip can get smaller over time */ 896706f2543Smrg RegionCopy(portPriv->clientClip, portPriv->pCompositeClip); 897706f2543Smrg RegionTranslate(portPriv->clientClip, 898706f2543Smrg -portPriv->pDraw->x, -portPriv->pDraw->y); 899706f2543Smrg 900706f2543Smrg /* translate the video region to the screen */ 901706f2543Smrg WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x; 902706f2543Smrg WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y; 903706f2543Smrg WinBox.x2 = WinBox.x1 + portPriv->drw_w; 904706f2543Smrg WinBox.y2 = WinBox.y1 + portPriv->drw_h; 905706f2543Smrg 906706f2543Smrg /* clip to the window composite clip */ 907706f2543Smrg RegionInit(&WinRegion, &WinBox, 1); 908706f2543Smrg RegionNull(&ClipRegion); 909706f2543Smrg RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip); 910706f2543Smrg 911706f2543Smrg /* clip and translate to the viewport */ 912706f2543Smrg if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { 913706f2543Smrg RegionRec VPReg; 914706f2543Smrg BoxRec VPBox; 915706f2543Smrg 916706f2543Smrg VPBox.x1 = portPriv->pScrn->frameX0; 917706f2543Smrg VPBox.y1 = portPriv->pScrn->frameY0; 918706f2543Smrg VPBox.x2 = portPriv->pScrn->frameX1 + 1; 919706f2543Smrg VPBox.y2 = portPriv->pScrn->frameY1 + 1; 920706f2543Smrg 921706f2543Smrg RegionInit(&VPReg, &VPBox, 1); 922706f2543Smrg RegionIntersect(&ClipRegion, &ClipRegion, &VPReg); 923706f2543Smrg RegionUninit(&VPReg); 924706f2543Smrg } 925706f2543Smrg 926706f2543Smrg /* that's all if it's totally obscured */ 927706f2543Smrg if(!RegionNotEmpty(&ClipRegion)) { 928706f2543Smrg clippedAway = TRUE; 929706f2543Smrg goto CLIP_VIDEO_BAILOUT; 930706f2543Smrg } 931706f2543Smrg 932706f2543Smrg /* bailout if we have to clip but the hardware doesn't support it */ 933706f2543Smrg if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) { 934706f2543Smrg BoxPtr clipBox = RegionRects(&ClipRegion); 935706f2543Smrg if( (RegionNumRects(&ClipRegion) != 1) || 936706f2543Smrg (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) || 937706f2543Smrg (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) 938706f2543Smrg { 939706f2543Smrg clippedAway = TRUE; 940706f2543Smrg goto CLIP_VIDEO_BAILOUT; 941706f2543Smrg } 942706f2543Smrg } 943706f2543Smrg 944706f2543Smrg if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { 945706f2543Smrg RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion); 946706f2543Smrg } 947706f2543Smrg 948706f2543Smrg ret = (*portPriv->AdaptorRec->ReputImage)(portPriv->pScrn, 949706f2543Smrg portPriv->vid_x, portPriv->vid_y, 950706f2543Smrg WinBox.x1, WinBox.y1, 951706f2543Smrg portPriv->vid_w, portPriv->vid_h, 952706f2543Smrg portPriv->drw_w, portPriv->drw_h, 953706f2543Smrg &ClipRegion, portPriv->DevPriv.ptr, 954706f2543Smrg portPriv->pDraw); 955706f2543Smrg 956706f2543Smrg portPriv->isOn = (ret == Success) ? XV_ON : XV_OFF; 957706f2543Smrg 958706f2543SmrgCLIP_VIDEO_BAILOUT: 959706f2543Smrg 960706f2543Smrg if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { 961706f2543Smrg (*portPriv->AdaptorRec->StopVideo)( 962706f2543Smrg portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); 963706f2543Smrg portPriv->isOn = XV_PENDING; 964706f2543Smrg } 965706f2543Smrg 966706f2543Smrg /* This clip was copied and only good for one shot */ 967706f2543Smrg if(!portPriv->FreeCompositeClip) 968706f2543Smrg portPriv->pCompositeClip = NULL; 969706f2543Smrg 970706f2543Smrg RegionUninit(&WinRegion); 971706f2543Smrg RegionUninit(&ClipRegion); 972706f2543Smrg 973706f2543Smrg return ret; 974706f2543Smrg} 975706f2543Smrg 976706f2543Smrg 977706f2543Smrgstatic int 978706f2543Smrgxf86XVReputAllVideo(WindowPtr pWin, pointer data) 979706f2543Smrg{ 980706f2543Smrg XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin); 981706f2543Smrg 982706f2543Smrg while(WinPriv) { 983706f2543Smrg if(WinPriv->PortRec->type == XvInputMask) 984706f2543Smrg xf86XVReputVideo(WinPriv->PortRec); 985706f2543Smrg else 986706f2543Smrg xf86XVRegetVideo(WinPriv->PortRec); 987706f2543Smrg WinPriv = WinPriv->next; 988706f2543Smrg } 989706f2543Smrg 990706f2543Smrg return WT_WALKCHILDREN; 991706f2543Smrg} 992706f2543Smrg 993706f2543Smrgstatic int 994706f2543Smrgxf86XVEnlistPortInWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv) 995706f2543Smrg{ 996706f2543Smrg XF86XVWindowPtr winPriv, PrivRoot; 997706f2543Smrg 998706f2543Smrg winPriv = PrivRoot = GET_XF86XV_WINDOW(pWin); 999706f2543Smrg 1000706f2543Smrg /* Enlist our port in the window private */ 1001706f2543Smrg while(winPriv) { 1002706f2543Smrg if(winPriv->PortRec == portPriv) /* we're already listed */ 1003706f2543Smrg break; 1004706f2543Smrg winPriv = winPriv->next; 1005706f2543Smrg } 1006706f2543Smrg 1007706f2543Smrg if(!winPriv) { 1008706f2543Smrg winPriv = calloc(1, sizeof(XF86XVWindowRec)); 1009706f2543Smrg if(!winPriv) return BadAlloc; 1010706f2543Smrg winPriv->PortRec = portPriv; 1011706f2543Smrg winPriv->next = PrivRoot; 1012706f2543Smrg dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, winPriv); 1013706f2543Smrg } 1014706f2543Smrg 1015706f2543Smrg portPriv->pDraw = (DrawablePtr)pWin; 1016706f2543Smrg 1017706f2543Smrg return Success; 1018706f2543Smrg} 1019706f2543Smrg 1020706f2543Smrg 1021706f2543Smrgstatic void 1022706f2543Smrgxf86XVRemovePortFromWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv) 1023706f2543Smrg{ 1024706f2543Smrg XF86XVWindowPtr winPriv, prevPriv = NULL; 1025706f2543Smrg winPriv = GET_XF86XV_WINDOW(pWin); 1026706f2543Smrg 1027706f2543Smrg while(winPriv) { 1028706f2543Smrg if(winPriv->PortRec == portPriv) { 1029706f2543Smrg if(prevPriv) 1030706f2543Smrg prevPriv->next = winPriv->next; 1031706f2543Smrg else 1032706f2543Smrg dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, 1033706f2543Smrg winPriv->next); 1034706f2543Smrg free(winPriv); 1035706f2543Smrg break; 1036706f2543Smrg } 1037706f2543Smrg prevPriv = winPriv; 1038706f2543Smrg winPriv = winPriv->next; 1039706f2543Smrg } 1040706f2543Smrg portPriv->pDraw = NULL; 1041706f2543Smrg if (portPriv->ckeyFilled) { 1042706f2543Smrg RegionDestroy(portPriv->ckeyFilled); 1043706f2543Smrg portPriv->ckeyFilled = NULL; 1044706f2543Smrg } 1045706f2543Smrg portPriv->clipChanged = FALSE; 1046706f2543Smrg} 1047706f2543Smrg 1048706f2543Smrgstatic void 1049706f2543Smrgxf86XVReputOrStopPort(XvPortRecPrivatePtr pPriv, 1050706f2543Smrg WindowPtr pWin, 1051706f2543Smrg Bool visible) 1052706f2543Smrg{ 1053706f2543Smrg if (!visible) { 1054706f2543Smrg if (pPriv->isOn == XV_ON) { 1055706f2543Smrg (*pPriv->AdaptorRec->StopVideo)(pPriv->pScrn, pPriv->DevPriv.ptr, FALSE); 1056706f2543Smrg pPriv->isOn = XV_PENDING; 1057706f2543Smrg } 1058706f2543Smrg 1059706f2543Smrg if (!pPriv->type) /* overlaid still/image*/ 1060706f2543Smrg xf86XVRemovePortFromWindow(pWin, pPriv); 1061706f2543Smrg 1062706f2543Smrg return; 1063706f2543Smrg } 1064706f2543Smrg 1065706f2543Smrg switch (pPriv->type) { 1066706f2543Smrg case XvInputMask: 1067706f2543Smrg xf86XVReputVideo(pPriv); 1068706f2543Smrg break; 1069706f2543Smrg case XvOutputMask: 1070706f2543Smrg xf86XVRegetVideo(pPriv); 1071706f2543Smrg break; 1072706f2543Smrg default: /* overlaid still/image*/ 1073706f2543Smrg if (pPriv->AdaptorRec->ReputImage) 1074706f2543Smrg xf86XVReputImage(pPriv); 1075706f2543Smrg break; 1076706f2543Smrg } 1077706f2543Smrg} 1078706f2543Smrg 1079706f2543Smrgstatic void 1080706f2543Smrgxf86XVReputOrStopAllPorts(ScrnInfoPtr pScrn, Bool onlyChanged) 1081706f2543Smrg{ 1082706f2543Smrg ScreenPtr pScreen = pScrn->pScreen; 1083706f2543Smrg XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); 1084706f2543Smrg XvAdaptorPtr pa; 1085706f2543Smrg int c, i; 1086706f2543Smrg 1087706f2543Smrg for (c = pxvs->nAdaptors, pa = pxvs->pAdaptors; c > 0; c--, pa++) { 1088706f2543Smrg XvPortPtr pPort = pa->pPorts; 1089706f2543Smrg 1090706f2543Smrg for (i = pa->nPorts; i > 0; i--, pPort++) { 1091706f2543Smrg XvPortRecPrivatePtr pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr; 1092706f2543Smrg WindowPtr pWin = (WindowPtr)pPriv->pDraw; 1093706f2543Smrg Bool visible; 1094706f2543Smrg 1095706f2543Smrg if (pPriv->isOn == XV_OFF || !pWin) 1096706f2543Smrg continue; 1097706f2543Smrg 1098706f2543Smrg if (onlyChanged && !pPriv->clipChanged) 1099706f2543Smrg continue; 1100706f2543Smrg 1101706f2543Smrg visible = pWin->visibility == VisibilityUnobscured || 1102706f2543Smrg pWin->visibility == VisibilityPartiallyObscured; 1103706f2543Smrg 1104706f2543Smrg /* 1105706f2543Smrg * Stop and remove still/images if 1106706f2543Smrg * ReputImage isn't supported. 1107706f2543Smrg */ 1108706f2543Smrg if (!pPriv->type && !pPriv->AdaptorRec->ReputImage) 1109706f2543Smrg visible = FALSE; 1110706f2543Smrg 1111706f2543Smrg xf86XVReputOrStopPort(pPriv, pWin, visible); 1112706f2543Smrg 1113706f2543Smrg pPriv->clipChanged = FALSE; 1114706f2543Smrg } 1115706f2543Smrg } 1116706f2543Smrg} 1117706f2543Smrg 1118706f2543Smrg/**** ScreenRec fields ****/ 1119706f2543Smrg 1120706f2543Smrgstatic Bool 1121706f2543Smrgxf86XVDestroyWindow(WindowPtr pWin) 1122706f2543Smrg{ 1123706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 1124706f2543Smrg XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); 1125706f2543Smrg XF86XVWindowPtr tmp, WinPriv = GET_XF86XV_WINDOW(pWin); 1126706f2543Smrg int ret; 1127706f2543Smrg 1128706f2543Smrg while(WinPriv) { 1129706f2543Smrg XvPortRecPrivatePtr pPriv = WinPriv->PortRec; 1130706f2543Smrg 1131706f2543Smrg if(pPriv->isOn > XV_OFF) { 1132706f2543Smrg (*pPriv->AdaptorRec->StopVideo)( 1133706f2543Smrg pPriv->pScrn, pPriv->DevPriv.ptr, TRUE); 1134706f2543Smrg pPriv->isOn = XV_OFF; 1135706f2543Smrg } 1136706f2543Smrg 1137706f2543Smrg pPriv->pDraw = NULL; 1138706f2543Smrg tmp = WinPriv; 1139706f2543Smrg WinPriv = WinPriv->next; 1140706f2543Smrg free(tmp); 1141706f2543Smrg } 1142706f2543Smrg 1143706f2543Smrg dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, NULL); 1144706f2543Smrg 1145706f2543Smrg pScreen->DestroyWindow = ScreenPriv->DestroyWindow; 1146706f2543Smrg ret = (*pScreen->DestroyWindow)(pWin); 1147706f2543Smrg pScreen->DestroyWindow = xf86XVDestroyWindow; 1148706f2543Smrg 1149706f2543Smrg return ret; 1150706f2543Smrg} 1151706f2543Smrg 1152706f2543Smrgstatic void 1153706f2543Smrgxf86XVPostValidateTree(WindowPtr pWin, WindowPtr pLayerWin, VTKind kind) 1154706f2543Smrg{ 1155706f2543Smrg ScreenPtr pScreen; 1156706f2543Smrg XF86XVScreenPtr ScreenPriv; 1157706f2543Smrg ScrnInfoPtr pScrn; 1158706f2543Smrg 1159706f2543Smrg if (pWin) 1160706f2543Smrg pScreen = pWin->drawable.pScreen; 1161706f2543Smrg else 1162706f2543Smrg pScreen = pLayerWin->drawable.pScreen; 1163706f2543Smrg 1164706f2543Smrg ScreenPriv = GET_XF86XV_SCREEN(pScreen); 1165706f2543Smrg pScrn = xf86Screens[pScreen->myNum]; 1166706f2543Smrg 1167706f2543Smrg xf86XVReputOrStopAllPorts(pScrn, TRUE); 1168706f2543Smrg 1169706f2543Smrg pScreen->PostValidateTree = ScreenPriv->PostValidateTree; 1170706f2543Smrg if (pScreen->PostValidateTree) { 1171706f2543Smrg (*pScreen->PostValidateTree)(pWin, pLayerWin, kind); 1172706f2543Smrg } 1173706f2543Smrg ScreenPriv->PostValidateTree = PostValidateTreeUndefined; 1174706f2543Smrg} 1175706f2543Smrg 1176706f2543Smrgstatic void 1177706f2543Smrgxf86XVWindowExposures(WindowPtr pWin, RegionPtr reg1, RegionPtr reg2) 1178706f2543Smrg{ 1179706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 1180706f2543Smrg XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); 1181706f2543Smrg XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin); 1182706f2543Smrg XvPortRecPrivatePtr pPriv; 1183706f2543Smrg Bool AreasExposed; 1184706f2543Smrg 1185706f2543Smrg AreasExposed = (WinPriv && reg1 && RegionNotEmpty(reg1)); 1186706f2543Smrg 1187706f2543Smrg pScreen->WindowExposures = ScreenPriv->WindowExposures; 1188706f2543Smrg (*pScreen->WindowExposures)(pWin, reg1, reg2); 1189706f2543Smrg pScreen->WindowExposures = xf86XVWindowExposures; 1190706f2543Smrg 1191706f2543Smrg /* filter out XClearWindow/Area */ 1192706f2543Smrg if (!pWin->valdata) return; 1193706f2543Smrg 1194706f2543Smrg while(WinPriv) { 1195706f2543Smrg Bool visible = TRUE; 1196706f2543Smrg 1197706f2543Smrg pPriv = WinPriv->PortRec; 1198706f2543Smrg 1199706f2543Smrg /* 1200706f2543Smrg * Stop and remove still/images if areas were exposed and 1201706f2543Smrg * ReputImage isn't supported. 1202706f2543Smrg */ 1203706f2543Smrg if (!pPriv->type && !pPriv->AdaptorRec->ReputImage) 1204706f2543Smrg visible = !AreasExposed; 1205706f2543Smrg 1206706f2543Smrg /* 1207706f2543Smrg * Subtract exposed areas from overlaid image to match textured video 1208706f2543Smrg * behavior. 1209706f2543Smrg */ 1210706f2543Smrg if (!pPriv->type && pPriv->clientClip) 1211706f2543Smrg RegionSubtract(pPriv->clientClip, pPriv->clientClip, reg1); 1212706f2543Smrg 1213706f2543Smrg if (visible && pPriv->ckeyFilled) { 1214706f2543Smrg RegionRec tmp; 1215706f2543Smrg RegionNull(&tmp); 1216706f2543Smrg RegionCopy(&tmp, reg1); 1217706f2543Smrg RegionTranslate(&tmp, pWin->drawable.x, pWin->drawable.y); 1218706f2543Smrg RegionSubtract(pPriv->ckeyFilled, pPriv->ckeyFilled, &tmp); 1219706f2543Smrg } 1220706f2543Smrg 1221706f2543Smrg WinPriv = WinPriv->next; 1222706f2543Smrg xf86XVReputOrStopPort(pPriv, pWin, visible); 1223706f2543Smrg 1224706f2543Smrg pPriv->clipChanged = FALSE; 1225706f2543Smrg } 1226706f2543Smrg} 1227706f2543Smrg 1228706f2543Smrgstatic void 1229706f2543Smrgxf86XVClipNotify(WindowPtr pWin, int dx, int dy) 1230706f2543Smrg{ 1231706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 1232706f2543Smrg XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); 1233706f2543Smrg XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin); 1234706f2543Smrg XvPortRecPrivatePtr pPriv; 1235706f2543Smrg 1236706f2543Smrg while(WinPriv) { 1237706f2543Smrg pPriv = WinPriv->PortRec; 1238706f2543Smrg 1239706f2543Smrg if(pPriv->pCompositeClip && pPriv->FreeCompositeClip) 1240706f2543Smrg RegionDestroy(pPriv->pCompositeClip); 1241706f2543Smrg 1242706f2543Smrg pPriv->pCompositeClip = NULL; 1243706f2543Smrg 1244706f2543Smrg if (pPriv->AdaptorRec->ClipNotify) 1245706f2543Smrg (*pPriv->AdaptorRec->ClipNotify)(pPriv->pScrn, pPriv->DevPriv.ptr, 1246706f2543Smrg pWin, dx, dy); 1247706f2543Smrg 1248706f2543Smrg pPriv->clipChanged = TRUE; 1249706f2543Smrg 1250706f2543Smrg if (ScreenPriv->PostValidateTree == PostValidateTreeUndefined) { 1251706f2543Smrg ScreenPriv->PostValidateTree = pScreen->PostValidateTree; 1252706f2543Smrg pScreen->PostValidateTree = xf86XVPostValidateTree; 1253706f2543Smrg } 1254706f2543Smrg 1255706f2543Smrg WinPriv = WinPriv->next; 1256706f2543Smrg } 1257706f2543Smrg 1258706f2543Smrg if(ScreenPriv->ClipNotify) { 1259706f2543Smrg pScreen->ClipNotify = ScreenPriv->ClipNotify; 1260706f2543Smrg (*pScreen->ClipNotify)(pWin, dx, dy); 1261706f2543Smrg pScreen->ClipNotify = xf86XVClipNotify; 1262706f2543Smrg } 1263706f2543Smrg} 1264706f2543Smrg 1265706f2543Smrg 1266706f2543Smrg 1267706f2543Smrg/**** Required XvScreenRec fields ****/ 1268706f2543Smrg 1269706f2543Smrgstatic Bool 1270706f2543Smrgxf86XVCloseScreen(int i, ScreenPtr pScreen) 1271706f2543Smrg{ 1272706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1273706f2543Smrg XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); 1274706f2543Smrg XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); 1275706f2543Smrg XvAdaptorPtr pa; 1276706f2543Smrg int c; 1277706f2543Smrg 1278706f2543Smrg if(!ScreenPriv) return TRUE; 1279706f2543Smrg 1280706f2543Smrg pScreen->DestroyWindow = ScreenPriv->DestroyWindow; 1281706f2543Smrg pScreen->WindowExposures = ScreenPriv->WindowExposures; 1282706f2543Smrg pScreen->ClipNotify = ScreenPriv->ClipNotify; 1283706f2543Smrg 1284706f2543Smrg pScrn->EnterVT = ScreenPriv->EnterVT; 1285706f2543Smrg pScrn->LeaveVT = ScreenPriv->LeaveVT; 1286706f2543Smrg pScrn->AdjustFrame = ScreenPriv->AdjustFrame; 1287706f2543Smrg pScrn->ModeSet = ScreenPriv->ModeSet; 1288706f2543Smrg 1289706f2543Smrg for(c = 0, pa = pxvs->pAdaptors; c < pxvs->nAdaptors; c++, pa++) { 1290706f2543Smrg xf86XVFreeAdaptor(pa); 1291706f2543Smrg } 1292706f2543Smrg 1293706f2543Smrg free(pxvs->pAdaptors); 1294706f2543Smrg free(ScreenPriv); 1295706f2543Smrg return TRUE; 1296706f2543Smrg} 1297706f2543Smrg 1298706f2543Smrg 1299706f2543Smrgstatic int 1300706f2543Smrgxf86XVQueryAdaptors( 1301706f2543Smrg ScreenPtr pScreen, 1302706f2543Smrg XvAdaptorPtr *p_pAdaptors, 1303706f2543Smrg int *p_nAdaptors 1304706f2543Smrg){ 1305706f2543Smrg XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); 1306706f2543Smrg 1307706f2543Smrg *p_nAdaptors = pxvs->nAdaptors; 1308706f2543Smrg *p_pAdaptors = pxvs->pAdaptors; 1309706f2543Smrg 1310706f2543Smrg return Success; 1311706f2543Smrg} 1312706f2543Smrg 1313706f2543Smrg 1314706f2543Smrg/**** ScrnInfoRec fields ****/ 1315706f2543Smrg 1316706f2543Smrgstatic Bool 1317706f2543Smrgxf86XVEnterVT(int index, int flags) 1318706f2543Smrg{ 1319706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[index]; 1320706f2543Smrg ScreenPtr pScreen = screenInfo.screens[index]; 1321706f2543Smrg XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); 1322706f2543Smrg Bool ret; 1323706f2543Smrg 1324706f2543Smrg pScrn->EnterVT = ScreenPriv->EnterVT; 1325706f2543Smrg ret = (*ScreenPriv->EnterVT)(index, flags); 1326706f2543Smrg ScreenPriv->EnterVT = pScrn->EnterVT; 1327706f2543Smrg pScrn->EnterVT = xf86XVEnterVT; 1328706f2543Smrg 1329706f2543Smrg if(ret) WalkTree(pScreen, xf86XVReputAllVideo, 0); 1330706f2543Smrg 1331706f2543Smrg return ret; 1332706f2543Smrg} 1333706f2543Smrg 1334706f2543Smrgstatic void 1335706f2543Smrgxf86XVLeaveVT(int index, int flags) 1336706f2543Smrg{ 1337706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[index]; 1338706f2543Smrg ScreenPtr pScreen = screenInfo.screens[index]; 1339706f2543Smrg XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); 1340706f2543Smrg XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); 1341706f2543Smrg XvAdaptorPtr pAdaptor; 1342706f2543Smrg XvPortPtr pPort; 1343706f2543Smrg XvPortRecPrivatePtr pPriv; 1344706f2543Smrg int i, j; 1345706f2543Smrg 1346706f2543Smrg for(i = 0; i < pxvs->nAdaptors; i++) { 1347706f2543Smrg pAdaptor = &pxvs->pAdaptors[i]; 1348706f2543Smrg for(j = 0; j < pAdaptor->nPorts; j++) { 1349706f2543Smrg pPort = &pAdaptor->pPorts[j]; 1350706f2543Smrg pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr; 1351706f2543Smrg if(pPriv->isOn > XV_OFF) { 1352706f2543Smrg 1353706f2543Smrg (*pPriv->AdaptorRec->StopVideo)( 1354706f2543Smrg pPriv->pScrn, pPriv->DevPriv.ptr, TRUE); 1355706f2543Smrg pPriv->isOn = XV_OFF; 1356706f2543Smrg 1357706f2543Smrg if(pPriv->pCompositeClip && pPriv->FreeCompositeClip) 1358706f2543Smrg RegionDestroy(pPriv->pCompositeClip); 1359706f2543Smrg 1360706f2543Smrg pPriv->pCompositeClip = NULL; 1361706f2543Smrg 1362706f2543Smrg if(!pPriv->type && pPriv->pDraw) { /* still */ 1363706f2543Smrg xf86XVRemovePortFromWindow((WindowPtr)pPriv->pDraw, pPriv); 1364706f2543Smrg } 1365706f2543Smrg } 1366706f2543Smrg } 1367706f2543Smrg } 1368706f2543Smrg 1369706f2543Smrg pScrn->LeaveVT = ScreenPriv->LeaveVT; 1370706f2543Smrg (*ScreenPriv->LeaveVT)(index, flags); 1371706f2543Smrg ScreenPriv->LeaveVT = pScrn->LeaveVT; 1372706f2543Smrg pScrn->LeaveVT = xf86XVLeaveVT; 1373706f2543Smrg} 1374706f2543Smrg 1375706f2543Smrgstatic void 1376706f2543Smrgxf86XVAdjustFrame(int index, int x, int y, int flags) 1377706f2543Smrg{ 1378706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[index]; 1379706f2543Smrg ScreenPtr pScreen = pScrn->pScreen; 1380706f2543Smrg XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); 1381706f2543Smrg 1382706f2543Smrg if(ScreenPriv->AdjustFrame) { 1383706f2543Smrg pScrn->AdjustFrame = ScreenPriv->AdjustFrame; 1384706f2543Smrg (*pScrn->AdjustFrame)(index, x, y, flags); 1385706f2543Smrg pScrn->AdjustFrame = xf86XVAdjustFrame; 1386706f2543Smrg } 1387706f2543Smrg 1388706f2543Smrg xf86XVReputOrStopAllPorts(pScrn, FALSE); 1389706f2543Smrg} 1390706f2543Smrg 1391706f2543Smrgstatic void 1392706f2543Smrgxf86XVModeSet(ScrnInfoPtr pScrn) 1393706f2543Smrg{ 1394706f2543Smrg ScreenPtr pScreen = pScrn->pScreen; 1395706f2543Smrg XF86XVScreenPtr ScreenPriv; 1396706f2543Smrg 1397706f2543Smrg /* Can be called before pScrn->pScreen is set */ 1398706f2543Smrg if (!pScreen) 1399706f2543Smrg return; 1400706f2543Smrg 1401706f2543Smrg ScreenPriv = GET_XF86XV_SCREEN(pScreen); 1402706f2543Smrg 1403706f2543Smrg if (ScreenPriv->ModeSet) { 1404706f2543Smrg pScrn->ModeSet = ScreenPriv->ModeSet; 1405706f2543Smrg (*pScrn->ModeSet)(pScrn); 1406706f2543Smrg pScrn->ModeSet = xf86XVModeSet; 1407706f2543Smrg } 1408706f2543Smrg 1409706f2543Smrg xf86XVReputOrStopAllPorts(pScrn, FALSE); 1410706f2543Smrg} 1411706f2543Smrg 1412706f2543Smrg/**** XvAdaptorRec fields ****/ 1413706f2543Smrg 1414706f2543Smrgstatic int 1415706f2543Smrgxf86XVAllocatePort( 1416706f2543Smrg unsigned long port, 1417706f2543Smrg XvPortPtr pPort, 1418706f2543Smrg XvPortPtr *ppPort 1419706f2543Smrg){ 1420706f2543Smrg *ppPort = pPort; 1421706f2543Smrg return Success; 1422706f2543Smrg} 1423706f2543Smrg 1424706f2543Smrg 1425706f2543Smrg 1426706f2543Smrgstatic int 1427706f2543Smrgxf86XVFreePort(XvPortPtr pPort) 1428706f2543Smrg{ 1429706f2543Smrg return Success; 1430706f2543Smrg} 1431706f2543Smrg 1432706f2543Smrg 1433706f2543Smrgstatic int 1434706f2543Smrgxf86XVPutVideo( 1435706f2543Smrg ClientPtr client, 1436706f2543Smrg DrawablePtr pDraw, 1437706f2543Smrg XvPortPtr pPort, 1438706f2543Smrg GCPtr pGC, 1439706f2543Smrg INT16 vid_x, INT16 vid_y, 1440706f2543Smrg CARD16 vid_w, CARD16 vid_h, 1441706f2543Smrg INT16 drw_x, INT16 drw_y, 1442706f2543Smrg CARD16 drw_w, CARD16 drw_h 1443706f2543Smrg){ 1444706f2543Smrg XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); 1445706f2543Smrg int result; 1446706f2543Smrg 1447706f2543Smrg /* No dumping video to pixmaps... For now anyhow */ 1448706f2543Smrg if(pDraw->type != DRAWABLE_WINDOW) { 1449706f2543Smrg pPort->pDraw = (DrawablePtr)NULL; 1450706f2543Smrg return BadAlloc; 1451706f2543Smrg } 1452706f2543Smrg 1453706f2543Smrg /* If we are changing windows, unregister our port in the old window */ 1454706f2543Smrg if(portPriv->pDraw && (portPriv->pDraw != pDraw)) 1455706f2543Smrg xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); 1456706f2543Smrg 1457706f2543Smrg /* Register our port with the new window */ 1458706f2543Smrg result = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv); 1459706f2543Smrg if(result != Success) return result; 1460706f2543Smrg 1461706f2543Smrg portPriv->type = XvInputMask; 1462706f2543Smrg 1463706f2543Smrg /* save a copy of these parameters */ 1464706f2543Smrg portPriv->vid_x = vid_x; portPriv->vid_y = vid_y; 1465706f2543Smrg portPriv->vid_w = vid_w; portPriv->vid_h = vid_h; 1466706f2543Smrg portPriv->drw_x = drw_x; portPriv->drw_y = drw_y; 1467706f2543Smrg portPriv->drw_w = drw_w; portPriv->drw_h = drw_h; 1468706f2543Smrg 1469706f2543Smrg /* make sure we have the most recent copy of the clientClip */ 1470706f2543Smrg xf86XVCopyClip(portPriv, pGC); 1471706f2543Smrg 1472706f2543Smrg /* To indicate to the DI layer that we were successful */ 1473706f2543Smrg pPort->pDraw = pDraw; 1474706f2543Smrg 1475706f2543Smrg if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ 1476706f2543Smrg 1477706f2543Smrg return(xf86XVReputVideo(portPriv)); 1478706f2543Smrg} 1479706f2543Smrg 1480706f2543Smrgstatic int 1481706f2543Smrgxf86XVPutStill( 1482706f2543Smrg ClientPtr client, 1483706f2543Smrg DrawablePtr pDraw, 1484706f2543Smrg XvPortPtr pPort, 1485706f2543Smrg GCPtr pGC, 1486706f2543Smrg INT16 vid_x, INT16 vid_y, 1487706f2543Smrg CARD16 vid_w, CARD16 vid_h, 1488706f2543Smrg INT16 drw_x, INT16 drw_y, 1489706f2543Smrg CARD16 drw_w, CARD16 drw_h 1490706f2543Smrg){ 1491706f2543Smrg XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); 1492706f2543Smrg RegionRec WinRegion; 1493706f2543Smrg RegionRec ClipRegion; 1494706f2543Smrg BoxRec WinBox; 1495706f2543Smrg int ret = Success; 1496706f2543Smrg Bool clippedAway = FALSE; 1497706f2543Smrg 1498706f2543Smrg if (pDraw->type != DRAWABLE_WINDOW) 1499706f2543Smrg return BadAlloc; 1500706f2543Smrg 1501706f2543Smrg if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ 1502706f2543Smrg 1503706f2543Smrg WinBox.x1 = pDraw->x + drw_x; 1504706f2543Smrg WinBox.y1 = pDraw->y + drw_y; 1505706f2543Smrg WinBox.x2 = WinBox.x1 + drw_w; 1506706f2543Smrg WinBox.y2 = WinBox.y1 + drw_h; 1507706f2543Smrg 1508706f2543Smrg xf86XVCopyCompositeClip(portPriv, pGC, pDraw); 1509706f2543Smrg 1510706f2543Smrg RegionInit(&WinRegion, &WinBox, 1); 1511706f2543Smrg RegionNull(&ClipRegion); 1512706f2543Smrg RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip); 1513706f2543Smrg 1514706f2543Smrg if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { 1515706f2543Smrg RegionRec VPReg; 1516706f2543Smrg BoxRec VPBox; 1517706f2543Smrg 1518706f2543Smrg VPBox.x1 = portPriv->pScrn->frameX0; 1519706f2543Smrg VPBox.y1 = portPriv->pScrn->frameY0; 1520706f2543Smrg VPBox.x2 = portPriv->pScrn->frameX1 + 1; 1521706f2543Smrg VPBox.y2 = portPriv->pScrn->frameY1 + 1; 1522706f2543Smrg 1523706f2543Smrg RegionInit(&VPReg, &VPBox, 1); 1524706f2543Smrg RegionIntersect(&ClipRegion, &ClipRegion, &VPReg); 1525706f2543Smrg RegionUninit(&VPReg); 1526706f2543Smrg } 1527706f2543Smrg 1528706f2543Smrg if(portPriv->pDraw) { 1529706f2543Smrg xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); 1530706f2543Smrg } 1531706f2543Smrg 1532706f2543Smrg if(!RegionNotEmpty(&ClipRegion)) { 1533706f2543Smrg clippedAway = TRUE; 1534706f2543Smrg goto PUT_STILL_BAILOUT; 1535706f2543Smrg } 1536706f2543Smrg 1537706f2543Smrg if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) { 1538706f2543Smrg BoxPtr clipBox = RegionRects(&ClipRegion); 1539706f2543Smrg if( (RegionNumRects(&ClipRegion) != 1) || 1540706f2543Smrg (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) || 1541706f2543Smrg (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) 1542706f2543Smrg { 1543706f2543Smrg clippedAway = TRUE; 1544706f2543Smrg goto PUT_STILL_BAILOUT; 1545706f2543Smrg } 1546706f2543Smrg } 1547706f2543Smrg 1548706f2543Smrg if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { 1549706f2543Smrg RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion); 1550706f2543Smrg } 1551706f2543Smrg 1552706f2543Smrg ret = (*portPriv->AdaptorRec->PutStill)(portPriv->pScrn, 1553706f2543Smrg vid_x, vid_y, WinBox.x1, WinBox.y1, 1554706f2543Smrg vid_w, vid_h, drw_w, drw_h, 1555706f2543Smrg &ClipRegion, portPriv->DevPriv.ptr, 1556706f2543Smrg pDraw); 1557706f2543Smrg 1558706f2543Smrg if((ret == Success) && 1559706f2543Smrg (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_STILLS)) { 1560706f2543Smrg 1561706f2543Smrg xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv); 1562706f2543Smrg portPriv->isOn = XV_ON; 1563706f2543Smrg portPriv->vid_x = vid_x; portPriv->vid_y = vid_y; 1564706f2543Smrg portPriv->vid_w = vid_w; portPriv->vid_h = vid_h; 1565706f2543Smrg portPriv->drw_x = drw_x; portPriv->drw_y = drw_y; 1566706f2543Smrg portPriv->drw_w = drw_w; portPriv->drw_h = drw_h; 1567706f2543Smrg portPriv->type = 0; /* no mask means it's transient and should 1568706f2543Smrg not be reput once it's removed */ 1569706f2543Smrg pPort->pDraw = pDraw; /* make sure we can get stop requests */ 1570706f2543Smrg } 1571706f2543Smrg 1572706f2543SmrgPUT_STILL_BAILOUT: 1573706f2543Smrg 1574706f2543Smrg if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { 1575706f2543Smrg (*portPriv->AdaptorRec->StopVideo)( 1576706f2543Smrg portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); 1577706f2543Smrg portPriv->isOn = XV_PENDING; 1578706f2543Smrg } 1579706f2543Smrg 1580706f2543Smrg /* This clip was copied and only good for one shot */ 1581706f2543Smrg if(!portPriv->FreeCompositeClip) 1582706f2543Smrg portPriv->pCompositeClip = NULL; 1583706f2543Smrg 1584706f2543Smrg RegionUninit(&WinRegion); 1585706f2543Smrg RegionUninit(&ClipRegion); 1586706f2543Smrg 1587706f2543Smrg return ret; 1588706f2543Smrg} 1589706f2543Smrg 1590706f2543Smrgstatic int 1591706f2543Smrgxf86XVGetVideo( 1592706f2543Smrg ClientPtr client, 1593706f2543Smrg DrawablePtr pDraw, 1594706f2543Smrg XvPortPtr pPort, 1595706f2543Smrg GCPtr pGC, 1596706f2543Smrg INT16 vid_x, INT16 vid_y, 1597706f2543Smrg CARD16 vid_w, CARD16 vid_h, 1598706f2543Smrg INT16 drw_x, INT16 drw_y, 1599706f2543Smrg CARD16 drw_w, CARD16 drw_h 1600706f2543Smrg){ 1601706f2543Smrg XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); 1602706f2543Smrg int result; 1603706f2543Smrg 1604706f2543Smrg /* No pixmaps... For now anyhow */ 1605706f2543Smrg if(pDraw->type != DRAWABLE_WINDOW) { 1606706f2543Smrg pPort->pDraw = (DrawablePtr)NULL; 1607706f2543Smrg return BadAlloc; 1608706f2543Smrg } 1609706f2543Smrg 1610706f2543Smrg /* If we are changing windows, unregister our port in the old window */ 1611706f2543Smrg if(portPriv->pDraw && (portPriv->pDraw != pDraw)) 1612706f2543Smrg xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); 1613706f2543Smrg 1614706f2543Smrg /* Register our port with the new window */ 1615706f2543Smrg result = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv); 1616706f2543Smrg if(result != Success) return result; 1617706f2543Smrg 1618706f2543Smrg portPriv->type = XvOutputMask; 1619706f2543Smrg 1620706f2543Smrg /* save a copy of these parameters */ 1621706f2543Smrg portPriv->vid_x = vid_x; portPriv->vid_y = vid_y; 1622706f2543Smrg portPriv->vid_w = vid_w; portPriv->vid_h = vid_h; 1623706f2543Smrg portPriv->drw_x = drw_x; portPriv->drw_y = drw_y; 1624706f2543Smrg portPriv->drw_w = drw_w; portPriv->drw_h = drw_h; 1625706f2543Smrg 1626706f2543Smrg /* make sure we have the most recent copy of the clientClip */ 1627706f2543Smrg xf86XVCopyClip(portPriv, pGC); 1628706f2543Smrg 1629706f2543Smrg /* To indicate to the DI layer that we were successful */ 1630706f2543Smrg pPort->pDraw = pDraw; 1631706f2543Smrg 1632706f2543Smrg if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ 1633706f2543Smrg 1634706f2543Smrg return(xf86XVRegetVideo(portPriv)); 1635706f2543Smrg} 1636706f2543Smrg 1637706f2543Smrgstatic int 1638706f2543Smrgxf86XVGetStill( 1639706f2543Smrg ClientPtr client, 1640706f2543Smrg DrawablePtr pDraw, 1641706f2543Smrg XvPortPtr pPort, 1642706f2543Smrg GCPtr pGC, 1643706f2543Smrg INT16 vid_x, INT16 vid_y, 1644706f2543Smrg CARD16 vid_w, CARD16 vid_h, 1645706f2543Smrg INT16 drw_x, INT16 drw_y, 1646706f2543Smrg CARD16 drw_w, CARD16 drw_h 1647706f2543Smrg){ 1648706f2543Smrg XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); 1649706f2543Smrg RegionRec WinRegion; 1650706f2543Smrg RegionRec ClipRegion; 1651706f2543Smrg BoxRec WinBox; 1652706f2543Smrg int ret = Success; 1653706f2543Smrg Bool clippedAway = FALSE; 1654706f2543Smrg 1655706f2543Smrg if (pDraw->type != DRAWABLE_WINDOW) 1656706f2543Smrg return BadAlloc; 1657706f2543Smrg 1658706f2543Smrg if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ 1659706f2543Smrg 1660706f2543Smrg WinBox.x1 = pDraw->x + drw_x; 1661706f2543Smrg WinBox.y1 = pDraw->y + drw_y; 1662706f2543Smrg WinBox.x2 = WinBox.x1 + drw_w; 1663706f2543Smrg WinBox.y2 = WinBox.y1 + drw_h; 1664706f2543Smrg 1665706f2543Smrg RegionInit(&WinRegion, &WinBox, 1); 1666706f2543Smrg RegionNull(&ClipRegion); 1667706f2543Smrg RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip); 1668706f2543Smrg 1669706f2543Smrg if(portPriv->pDraw) { 1670706f2543Smrg xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); 1671706f2543Smrg } 1672706f2543Smrg 1673706f2543Smrg if(!RegionNotEmpty(&ClipRegion)) { 1674706f2543Smrg clippedAway = TRUE; 1675706f2543Smrg goto GET_STILL_BAILOUT; 1676706f2543Smrg } 1677706f2543Smrg 1678706f2543Smrg if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { 1679706f2543Smrg RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion); 1680706f2543Smrg } 1681706f2543Smrg 1682706f2543Smrg ret = (*portPriv->AdaptorRec->GetStill)(portPriv->pScrn, 1683706f2543Smrg vid_x, vid_y, WinBox.x1, WinBox.y1, 1684706f2543Smrg vid_w, vid_h, drw_w, drw_h, 1685706f2543Smrg &ClipRegion, portPriv->DevPriv.ptr, 1686706f2543Smrg pDraw); 1687706f2543Smrg 1688706f2543SmrgGET_STILL_BAILOUT: 1689706f2543Smrg 1690706f2543Smrg if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { 1691706f2543Smrg (*portPriv->AdaptorRec->StopVideo)( 1692706f2543Smrg portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); 1693706f2543Smrg portPriv->isOn = XV_PENDING; 1694706f2543Smrg } 1695706f2543Smrg 1696706f2543Smrg RegionUninit(&WinRegion); 1697706f2543Smrg RegionUninit(&ClipRegion); 1698706f2543Smrg 1699706f2543Smrg return ret; 1700706f2543Smrg} 1701706f2543Smrg 1702706f2543Smrg 1703706f2543Smrg 1704706f2543Smrgstatic int 1705706f2543Smrgxf86XVStopVideo( 1706706f2543Smrg ClientPtr client, 1707706f2543Smrg XvPortPtr pPort, 1708706f2543Smrg DrawablePtr pDraw 1709706f2543Smrg){ 1710706f2543Smrg XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); 1711706f2543Smrg 1712706f2543Smrg if(pDraw->type != DRAWABLE_WINDOW) 1713706f2543Smrg return BadAlloc; 1714706f2543Smrg 1715706f2543Smrg xf86XVRemovePortFromWindow((WindowPtr)pDraw, portPriv); 1716706f2543Smrg 1717706f2543Smrg if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ 1718706f2543Smrg 1719706f2543Smrg /* Must free resources. */ 1720706f2543Smrg 1721706f2543Smrg if(portPriv->isOn > XV_OFF) { 1722706f2543Smrg (*portPriv->AdaptorRec->StopVideo)( 1723706f2543Smrg portPriv->pScrn, portPriv->DevPriv.ptr, TRUE); 1724706f2543Smrg portPriv->isOn = XV_OFF; 1725706f2543Smrg } 1726706f2543Smrg 1727706f2543Smrg return Success; 1728706f2543Smrg} 1729706f2543Smrg 1730706f2543Smrgstatic int 1731706f2543Smrgxf86XVSetPortAttribute( 1732706f2543Smrg ClientPtr client, 1733706f2543Smrg XvPortPtr pPort, 1734706f2543Smrg Atom attribute, 1735706f2543Smrg INT32 value 1736706f2543Smrg){ 1737706f2543Smrg XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); 1738706f2543Smrg 1739706f2543Smrg return((*portPriv->AdaptorRec->SetPortAttribute)(portPriv->pScrn, 1740706f2543Smrg attribute, value, portPriv->DevPriv.ptr)); 1741706f2543Smrg} 1742706f2543Smrg 1743706f2543Smrg 1744706f2543Smrgstatic int 1745706f2543Smrgxf86XVGetPortAttribute( 1746706f2543Smrg ClientPtr client, 1747706f2543Smrg XvPortPtr pPort, 1748706f2543Smrg Atom attribute, 1749706f2543Smrg INT32 *p_value 1750706f2543Smrg){ 1751706f2543Smrg XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); 1752706f2543Smrg 1753706f2543Smrg return((*portPriv->AdaptorRec->GetPortAttribute)(portPriv->pScrn, 1754706f2543Smrg attribute, p_value, portPriv->DevPriv.ptr)); 1755706f2543Smrg} 1756706f2543Smrg 1757706f2543Smrg 1758706f2543Smrg 1759706f2543Smrgstatic int 1760706f2543Smrgxf86XVQueryBestSize( 1761706f2543Smrg ClientPtr client, 1762706f2543Smrg XvPortPtr pPort, 1763706f2543Smrg CARD8 motion, 1764706f2543Smrg CARD16 vid_w, CARD16 vid_h, 1765706f2543Smrg CARD16 drw_w, CARD16 drw_h, 1766706f2543Smrg unsigned int *p_w, unsigned int *p_h 1767706f2543Smrg){ 1768706f2543Smrg XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); 1769706f2543Smrg 1770706f2543Smrg (*portPriv->AdaptorRec->QueryBestSize)(portPriv->pScrn, 1771706f2543Smrg (Bool)motion, vid_w, vid_h, drw_w, drw_h, 1772706f2543Smrg p_w, p_h, portPriv->DevPriv.ptr); 1773706f2543Smrg 1774706f2543Smrg return Success; 1775706f2543Smrg} 1776706f2543Smrg 1777706f2543Smrg 1778706f2543Smrgstatic int 1779706f2543Smrgxf86XVPutImage( 1780706f2543Smrg ClientPtr client, 1781706f2543Smrg DrawablePtr pDraw, 1782706f2543Smrg XvPortPtr pPort, 1783706f2543Smrg GCPtr pGC, 1784706f2543Smrg INT16 src_x, INT16 src_y, 1785706f2543Smrg CARD16 src_w, CARD16 src_h, 1786706f2543Smrg INT16 drw_x, INT16 drw_y, 1787706f2543Smrg CARD16 drw_w, CARD16 drw_h, 1788706f2543Smrg XvImagePtr format, 1789706f2543Smrg unsigned char* data, 1790706f2543Smrg Bool sync, 1791706f2543Smrg CARD16 width, CARD16 height 1792706f2543Smrg){ 1793706f2543Smrg XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); 1794706f2543Smrg RegionRec WinRegion; 1795706f2543Smrg RegionRec ClipRegion; 1796706f2543Smrg BoxRec WinBox; 1797706f2543Smrg int ret = Success; 1798706f2543Smrg Bool clippedAway = FALSE; 1799706f2543Smrg 1800706f2543Smrg if (pDraw->type != DRAWABLE_WINDOW) 1801706f2543Smrg return BadAlloc; 1802706f2543Smrg 1803706f2543Smrg if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ 1804706f2543Smrg 1805706f2543Smrg xf86XVCopyCompositeClip(portPriv, pGC, pDraw); 1806706f2543Smrg 1807706f2543Smrg WinBox.x1 = pDraw->x + drw_x; 1808706f2543Smrg WinBox.y1 = pDraw->y + drw_y; 1809706f2543Smrg WinBox.x2 = WinBox.x1 + drw_w; 1810706f2543Smrg WinBox.y2 = WinBox.y1 + drw_h; 1811706f2543Smrg 1812706f2543Smrg RegionInit(&WinRegion, &WinBox, 1); 1813706f2543Smrg RegionNull(&ClipRegion); 1814706f2543Smrg RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip); 1815706f2543Smrg 1816706f2543Smrg if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { 1817706f2543Smrg RegionRec VPReg; 1818706f2543Smrg BoxRec VPBox; 1819706f2543Smrg 1820706f2543Smrg VPBox.x1 = portPriv->pScrn->frameX0; 1821706f2543Smrg VPBox.y1 = portPriv->pScrn->frameY0; 1822706f2543Smrg VPBox.x2 = portPriv->pScrn->frameX1 + 1; 1823706f2543Smrg VPBox.y2 = portPriv->pScrn->frameY1 + 1; 1824706f2543Smrg 1825706f2543Smrg RegionInit(&VPReg, &VPBox, 1); 1826706f2543Smrg RegionIntersect(&ClipRegion, &ClipRegion, &VPReg); 1827706f2543Smrg RegionUninit(&VPReg); 1828706f2543Smrg } 1829706f2543Smrg 1830706f2543Smrg /* If we are changing windows, unregister our port in the old window */ 1831706f2543Smrg if(portPriv->pDraw && (portPriv->pDraw != pDraw)) 1832706f2543Smrg xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); 1833706f2543Smrg 1834706f2543Smrg /* Register our port with the new window */ 1835706f2543Smrg ret = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv); 1836706f2543Smrg if(ret != Success) goto PUT_IMAGE_BAILOUT; 1837706f2543Smrg 1838706f2543Smrg if(!RegionNotEmpty(&ClipRegion)) { 1839706f2543Smrg clippedAway = TRUE; 1840706f2543Smrg goto PUT_IMAGE_BAILOUT; 1841706f2543Smrg } 1842706f2543Smrg 1843706f2543Smrg if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) { 1844706f2543Smrg BoxPtr clipBox = RegionRects(&ClipRegion); 1845706f2543Smrg if( (RegionNumRects(&ClipRegion) != 1) || 1846706f2543Smrg (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) || 1847706f2543Smrg (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) 1848706f2543Smrg { 1849706f2543Smrg clippedAway = TRUE; 1850706f2543Smrg goto PUT_IMAGE_BAILOUT; 1851706f2543Smrg } 1852706f2543Smrg } 1853706f2543Smrg 1854706f2543Smrg if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { 1855706f2543Smrg RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion); 1856706f2543Smrg } 1857706f2543Smrg 1858706f2543Smrg ret = (*portPriv->AdaptorRec->PutImage)(portPriv->pScrn, 1859706f2543Smrg src_x, src_y, WinBox.x1, WinBox.y1, 1860706f2543Smrg src_w, src_h, drw_w, drw_h, format->id, data, width, height, 1861706f2543Smrg sync, &ClipRegion, portPriv->DevPriv.ptr, 1862706f2543Smrg pDraw); 1863706f2543Smrg 1864706f2543Smrg if((ret == Success) && 1865706f2543Smrg (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_IMAGES)) { 1866706f2543Smrg 1867706f2543Smrg portPriv->isOn = XV_ON; 1868706f2543Smrg portPriv->vid_x = src_x; portPriv->vid_y = src_y; 1869706f2543Smrg portPriv->vid_w = src_w; portPriv->vid_h = src_h; 1870706f2543Smrg portPriv->drw_x = drw_x; portPriv->drw_y = drw_y; 1871706f2543Smrg portPriv->drw_w = drw_w; portPriv->drw_h = drw_h; 1872706f2543Smrg portPriv->type = 0; /* no mask means it's transient and should 1873706f2543Smrg not be reput once it's removed */ 1874706f2543Smrg pPort->pDraw = pDraw; /* make sure we can get stop requests */ 1875706f2543Smrg } 1876706f2543Smrg 1877706f2543SmrgPUT_IMAGE_BAILOUT: 1878706f2543Smrg 1879706f2543Smrg if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { 1880706f2543Smrg (*portPriv->AdaptorRec->StopVideo)( 1881706f2543Smrg portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); 1882706f2543Smrg portPriv->isOn = XV_PENDING; 1883706f2543Smrg } 1884706f2543Smrg 1885706f2543Smrg /* This clip was copied and only good for one shot */ 1886706f2543Smrg if(!portPriv->FreeCompositeClip) 1887706f2543Smrg portPriv->pCompositeClip = NULL; 1888706f2543Smrg 1889706f2543Smrg RegionUninit(&WinRegion); 1890706f2543Smrg RegionUninit(&ClipRegion); 1891706f2543Smrg 1892706f2543Smrg return ret; 1893706f2543Smrg} 1894706f2543Smrg 1895706f2543Smrg 1896706f2543Smrgstatic int 1897706f2543Smrgxf86XVQueryImageAttributes( 1898706f2543Smrg ClientPtr client, 1899706f2543Smrg XvPortPtr pPort, 1900706f2543Smrg XvImagePtr format, 1901706f2543Smrg CARD16 *width, 1902706f2543Smrg CARD16 *height, 1903706f2543Smrg int *pitches, 1904706f2543Smrg int *offsets 1905706f2543Smrg){ 1906706f2543Smrg XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); 1907706f2543Smrg 1908706f2543Smrg return (*portPriv->AdaptorRec->QueryImageAttributes)(portPriv->pScrn, 1909706f2543Smrg format->id, width, height, pitches, offsets); 1910706f2543Smrg} 1911706f2543Smrg 1912706f2543Smrgvoid 1913706f2543Smrgxf86XVFillKeyHelperDrawable (DrawablePtr pDraw, CARD32 key, RegionPtr fillboxes) 1914706f2543Smrg{ 1915706f2543Smrg ScreenPtr pScreen = pDraw->pScreen; 1916706f2543Smrg ChangeGCVal pval[2]; 1917706f2543Smrg BoxPtr pbox = RegionRects(fillboxes); 1918706f2543Smrg int i, nbox = RegionNumRects(fillboxes); 1919706f2543Smrg xRectangle *rects; 1920706f2543Smrg GCPtr gc; 1921706f2543Smrg 1922706f2543Smrg if(!xf86Screens[pScreen->myNum]->vtSema) return; 1923706f2543Smrg 1924706f2543Smrg gc = GetScratchGC(pDraw->depth, pScreen); 1925706f2543Smrg pval[0].val = key; 1926706f2543Smrg pval[1].val = IncludeInferiors; 1927706f2543Smrg (void) ChangeGC(NullClient, gc, GCForeground|GCSubwindowMode, pval); 1928706f2543Smrg ValidateGC(pDraw, gc); 1929706f2543Smrg 1930706f2543Smrg rects = malloc(nbox * sizeof(xRectangle)); 1931706f2543Smrg 1932706f2543Smrg for(i = 0; i < nbox; i++, pbox++) 1933706f2543Smrg { 1934706f2543Smrg rects[i].x = pbox->x1 - pDraw->x; 1935706f2543Smrg rects[i].y = pbox->y1 - pDraw->y; 1936706f2543Smrg rects[i].width = pbox->x2 - pbox->x1; 1937706f2543Smrg rects[i].height = pbox->y2 - pbox->y1; 1938706f2543Smrg } 1939706f2543Smrg 1940706f2543Smrg (*gc->ops->PolyFillRect)(pDraw, gc, nbox, rects); 1941706f2543Smrg 1942706f2543Smrg free(rects); 1943706f2543Smrg FreeScratchGC (gc); 1944706f2543Smrg} 1945706f2543Smrg 1946706f2543Smrgvoid 1947706f2543Smrgxf86XVFillKeyHelper (ScreenPtr pScreen, CARD32 key, RegionPtr fillboxes) 1948706f2543Smrg{ 1949706f2543Smrg xf86XVFillKeyHelperDrawable (&pScreen->root->drawable, key, fillboxes); 1950706f2543Smrg} 1951706f2543Smrg 1952706f2543Smrgvoid 1953706f2543Smrgxf86XVFillKeyHelperPort (DrawablePtr pDraw, pointer data, CARD32 key, RegionPtr clipboxes, Bool fillEverything) 1954706f2543Smrg{ 1955706f2543Smrg WindowPtr pWin = (WindowPtr)pDraw; 1956706f2543Smrg XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin); 1957706f2543Smrg XvPortRecPrivatePtr portPriv = NULL; 1958706f2543Smrg RegionRec reg; 1959706f2543Smrg RegionPtr fillboxes; 1960706f2543Smrg 1961706f2543Smrg while (WinPriv) { 1962706f2543Smrg XvPortRecPrivatePtr pPriv = WinPriv->PortRec; 1963706f2543Smrg 1964706f2543Smrg if (data == pPriv->DevPriv.ptr) { 1965706f2543Smrg portPriv = pPriv; 1966706f2543Smrg break; 1967706f2543Smrg } 1968706f2543Smrg 1969706f2543Smrg WinPriv = WinPriv->next; 1970706f2543Smrg } 1971706f2543Smrg 1972706f2543Smrg if (!portPriv) 1973706f2543Smrg return; 1974706f2543Smrg 1975706f2543Smrg if (!portPriv->ckeyFilled) 1976706f2543Smrg portPriv->ckeyFilled = RegionCreate(NULL, 0); 1977706f2543Smrg 1978706f2543Smrg if (!fillEverything) { 1979706f2543Smrg RegionNull(®); 1980706f2543Smrg fillboxes = ® 1981706f2543Smrg RegionSubtract(fillboxes, clipboxes, portPriv->ckeyFilled); 1982706f2543Smrg 1983706f2543Smrg if (!RegionNotEmpty(fillboxes)) 1984706f2543Smrg goto out; 1985706f2543Smrg } else 1986706f2543Smrg fillboxes = clipboxes; 1987706f2543Smrg 1988706f2543Smrg 1989706f2543Smrg RegionCopy(portPriv->ckeyFilled, clipboxes); 1990706f2543Smrg 1991706f2543Smrg xf86XVFillKeyHelperDrawable(pDraw, key, fillboxes); 1992706f2543Smrgout: 1993706f2543Smrg if (!fillEverything) 1994706f2543Smrg RegionUninit(®); 1995706f2543Smrg} 1996706f2543Smrg 1997706f2543Smrg 1998706f2543Smrg/* xf86XVClipVideoHelper - 1999706f2543Smrg 2000706f2543Smrg Takes the dst box in standard X BoxRec form (top and left 2001706f2543Smrg edges inclusive, bottom and right exclusive). The new dst 2002706f2543Smrg box is returned. The source boundaries are given (x1, y1 2003706f2543Smrg inclusive, x2, y2 exclusive) and returned are the new source 2004706f2543Smrg boundaries in 16.16 fixed point. 2005706f2543Smrg*/ 2006706f2543Smrg 2007706f2543SmrgBool 2008706f2543Smrgxf86XVClipVideoHelper( 2009706f2543Smrg BoxPtr dst, 2010706f2543Smrg INT32 *xa, 2011706f2543Smrg INT32 *xb, 2012706f2543Smrg INT32 *ya, 2013706f2543Smrg INT32 *yb, 2014706f2543Smrg RegionPtr reg, 2015706f2543Smrg INT32 width, 2016706f2543Smrg INT32 height 2017706f2543Smrg){ 2018706f2543Smrg double xsw, xdw, ysw, ydw; 2019706f2543Smrg INT32 delta; 2020706f2543Smrg BoxPtr extents = RegionExtents(reg); 2021706f2543Smrg int diff; 2022706f2543Smrg 2023706f2543Smrg xsw = (*xb - *xa) << 16; 2024706f2543Smrg xdw = dst->x2 - dst->x1; 2025706f2543Smrg ysw = (*yb - *ya) << 16; 2026706f2543Smrg ydw = dst->y2 - dst->y1; 2027706f2543Smrg 2028706f2543Smrg *xa <<= 16; *xb <<= 16; 2029706f2543Smrg *ya <<= 16; *yb <<= 16; 2030706f2543Smrg 2031706f2543Smrg diff = extents->x1 - dst->x1; 2032706f2543Smrg if (diff > 0) { 2033706f2543Smrg dst->x1 = extents->x1; 2034706f2543Smrg *xa += (diff * xsw) / xdw; 2035706f2543Smrg } 2036706f2543Smrg diff = dst->x2 - extents->x2; 2037706f2543Smrg if (diff > 0) { 2038706f2543Smrg dst->x2 = extents->x2; 2039706f2543Smrg *xb -= (diff * xsw) / xdw; 2040706f2543Smrg } 2041706f2543Smrg diff = extents->y1 - dst->y1; 2042706f2543Smrg if (diff > 0) { 2043706f2543Smrg dst->y1 = extents->y1; 2044706f2543Smrg *ya += (diff * ysw) / ydw; 2045706f2543Smrg } 2046706f2543Smrg diff = dst->y2 - extents->y2; 2047706f2543Smrg if (diff > 0) { 2048706f2543Smrg dst->y2 = extents->y2; 2049706f2543Smrg *yb -= (diff * ysw) / ydw; 2050706f2543Smrg } 2051706f2543Smrg 2052706f2543Smrg if (*xa < 0) { 2053706f2543Smrg diff = (((-*xa) * xdw) + xsw - 1) / xsw; 2054706f2543Smrg dst->x1 += diff; 2055706f2543Smrg *xa += (diff * xsw) / xdw; 2056706f2543Smrg } 2057706f2543Smrg delta = *xb - (width << 16); 2058706f2543Smrg if (delta > 0) { 2059706f2543Smrg diff = ((delta * xdw) + xsw - 1) / xsw; 2060706f2543Smrg dst->x2 -= diff; 2061706f2543Smrg *xb -= (diff * xsw) / xdw; 2062706f2543Smrg } 2063706f2543Smrg if (*xa >= *xb) return FALSE; 2064706f2543Smrg 2065706f2543Smrg if (*ya < 0) { 2066706f2543Smrg diff = (((-*ya) * ydw) + ysw - 1) / ysw; 2067706f2543Smrg dst->y1 += diff; 2068706f2543Smrg *ya += (diff * ysw) / ydw; 2069706f2543Smrg } 2070706f2543Smrg delta = *yb - (height << 16); 2071706f2543Smrg if (delta > 0) { 2072706f2543Smrg diff = ((delta * ydw) + ysw - 1) / ysw; 2073706f2543Smrg dst->y2 -= diff; 2074706f2543Smrg *yb -= (diff * ysw) / ydw; 2075706f2543Smrg } 2076706f2543Smrg if (*ya >= *yb) return FALSE; 2077706f2543Smrg 2078706f2543Smrg if ((dst->x1 > extents->x1) || (dst->x2 < extents->x2) || 2079706f2543Smrg (dst->y1 > extents->y1) || (dst->y2 < extents->y2)) 2080706f2543Smrg { 2081706f2543Smrg RegionRec clipReg; 2082706f2543Smrg RegionInit(&clipReg, dst, 1); 2083706f2543Smrg RegionIntersect(reg, reg, &clipReg); 2084706f2543Smrg RegionUninit(&clipReg); 2085706f2543Smrg } 2086706f2543Smrg return TRUE; 2087706f2543Smrg} 2088706f2543Smrg 2089706f2543Smrgvoid 2090706f2543Smrgxf86XVCopyYUV12ToPacked( 2091706f2543Smrg const void *srcy, 2092706f2543Smrg const void *srcv, 2093706f2543Smrg const void *srcu, 2094706f2543Smrg void *dst, 2095706f2543Smrg int srcPitchy, 2096706f2543Smrg int srcPitchuv, 2097706f2543Smrg int dstPitch, 2098706f2543Smrg int h, 2099706f2543Smrg int w 2100706f2543Smrg){ 2101706f2543Smrg CARD32 *Dst; 2102706f2543Smrg const CARD8 *Y, *U, *V; 2103706f2543Smrg int i, j; 2104706f2543Smrg 2105706f2543Smrg w >>= 1; 2106706f2543Smrg 2107706f2543Smrg for (j = 0; j < h; j++) { 2108706f2543Smrg Dst = dst; 2109706f2543Smrg Y = srcy; V = srcv; U = srcu; 2110706f2543Smrg i = w; 2111706f2543Smrg while (i >= 4) { 2112706f2543Smrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN 2113706f2543Smrg Dst[0] = Y[0] | (Y[1] << 16) | (U[0] << 8) | (V[0] << 24); 2114706f2543Smrg Dst[1] = Y[2] | (Y[3] << 16) | (U[1] << 8) | (V[1] << 24); 2115706f2543Smrg Dst[2] = Y[4] | (Y[5] << 16) | (U[2] << 8) | (V[2] << 24); 2116706f2543Smrg Dst[3] = Y[6] | (Y[7] << 16) | (U[3] << 8) | (V[3] << 24); 2117706f2543Smrg#else 2118706f2543Smrg /* This assumes a little-endian framebuffer */ 2119706f2543Smrg Dst[0] = (Y[0] << 24) | (Y[1] << 8) | (U[0] << 16) | V[0]; 2120706f2543Smrg Dst[1] = (Y[2] << 24) | (Y[3] << 8) | (U[1] << 16) | V[1]; 2121706f2543Smrg Dst[2] = (Y[4] << 24) | (Y[5] << 8) | (U[2] << 16) | V[2]; 2122706f2543Smrg Dst[3] = (Y[6] << 24) | (Y[7] << 8) | (U[3] << 16) | V[3]; 2123706f2543Smrg#endif 2124706f2543Smrg Dst += 4; Y += 8; V += 4; U += 4; 2125706f2543Smrg i -= 4; 2126706f2543Smrg } 2127706f2543Smrg 2128706f2543Smrg while (i--) { 2129706f2543Smrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN 2130706f2543Smrg Dst[0] = Y[0] | (Y[1] << 16) | (U[0] << 8) | (V[0] << 24); 2131706f2543Smrg#else 2132706f2543Smrg /* This assumes a little-endian framebuffer */ 2133706f2543Smrg Dst[0] = (Y[0] << 24) | (Y[1] << 8) | (U[0] << 16) | V[0]; 2134706f2543Smrg#endif 2135706f2543Smrg Dst++; Y += 2; V++; U++; 2136706f2543Smrg } 2137706f2543Smrg 2138706f2543Smrg dst = (CARD8 *)dst + dstPitch; 2139706f2543Smrg srcy = (const CARD8 *)srcy + srcPitchy; 2140706f2543Smrg if (j & 1) { 2141706f2543Smrg srcu = (const CARD8 *)srcu + srcPitchuv; 2142706f2543Smrg srcv = (const CARD8 *)srcv + srcPitchuv; 2143706f2543Smrg } 2144706f2543Smrg } 2145706f2543Smrg} 2146706f2543Smrg 2147706f2543Smrgvoid 2148706f2543Smrgxf86XVCopyPacked( 2149706f2543Smrg const void *src, 2150706f2543Smrg void *dst, 2151706f2543Smrg int srcPitch, 2152706f2543Smrg int dstPitch, 2153706f2543Smrg int h, 2154706f2543Smrg int w 2155706f2543Smrg){ 2156706f2543Smrg const CARD32 *Src; 2157706f2543Smrg CARD32 *Dst; 2158706f2543Smrg int i; 2159706f2543Smrg 2160706f2543Smrg w >>= 1; 2161706f2543Smrg while (--h >= 0) { 2162706f2543Smrg do { 2163706f2543Smrg Dst = dst; Src = src; 2164706f2543Smrg i = w; 2165706f2543Smrg while (i >= 4) { 2166706f2543Smrg Dst[0] = Src[0]; 2167706f2543Smrg Dst[1] = Src[1]; 2168706f2543Smrg Dst[2] = Src[2]; 2169706f2543Smrg Dst[3] = Src[3]; 2170706f2543Smrg Dst += 4; Src += 4; i -= 4; 2171706f2543Smrg } 2172706f2543Smrg if (!i) break; 2173706f2543Smrg Dst[0] = Src[0]; 2174706f2543Smrg if (i == 1) break; 2175706f2543Smrg Dst[1] = Src[1]; 2176706f2543Smrg if (i == 2) break; 2177706f2543Smrg Dst[2] = Src[2]; 2178706f2543Smrg } while (0); 2179706f2543Smrg 2180706f2543Smrg src = (const CARD8 *)src + srcPitch; 2181706f2543Smrg dst = (CARD8 *)dst + dstPitch; 2182706f2543Smrg } 2183706f2543Smrg} 2184