xref: /OK3568_Linux_fs/external/xserver/hw/xfree86/common/xf86xv.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * XFree86 Xv DDX written by Mark Vojkovich (markv@valinux.com)
3*4882a593Smuzhiyun  */
4*4882a593Smuzhiyun /*
5*4882a593Smuzhiyun  * Copyright (c) 1998-2003 by The XFree86 Project, Inc.
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Permission is hereby granted, free of charge, to any person obtaining a
8*4882a593Smuzhiyun  * copy of this software and associated documentation files (the "Software"),
9*4882a593Smuzhiyun  * to deal in the Software without restriction, including without limitation
10*4882a593Smuzhiyun  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11*4882a593Smuzhiyun  * and/or sell copies of the Software, and to permit persons to whom the
12*4882a593Smuzhiyun  * Software is furnished to do so, subject to the following conditions:
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * The above copyright notice and this permission notice shall be included in
15*4882a593Smuzhiyun  * all copies or substantial portions of the Software.
16*4882a593Smuzhiyun  *
17*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18*4882a593Smuzhiyun  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19*4882a593Smuzhiyun  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20*4882a593Smuzhiyun  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
21*4882a593Smuzhiyun  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22*4882a593Smuzhiyun  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23*4882a593Smuzhiyun  * OTHER DEALINGS IN THE SOFTWARE.
24*4882a593Smuzhiyun  *
25*4882a593Smuzhiyun  * Except as contained in this notice, the name of the copyright holder(s)
26*4882a593Smuzhiyun  * and author(s) shall not be used in advertising or otherwise to promote
27*4882a593Smuzhiyun  * the sale, use or other dealings in this Software without prior written
28*4882a593Smuzhiyun  * authorization from the copyright holder(s) and author(s).
29*4882a593Smuzhiyun  */
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #ifdef HAVE_XORG_CONFIG_H
32*4882a593Smuzhiyun #include <xorg-config.h>
33*4882a593Smuzhiyun #endif
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #include "misc.h"
36*4882a593Smuzhiyun #include "xf86.h"
37*4882a593Smuzhiyun #include "xf86_OSproc.h"
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun #include <X11/X.h>
40*4882a593Smuzhiyun #include <X11/Xproto.h>
41*4882a593Smuzhiyun #include "scrnintstr.h"
42*4882a593Smuzhiyun #include "regionstr.h"
43*4882a593Smuzhiyun #include "windowstr.h"
44*4882a593Smuzhiyun #include "pixmapstr.h"
45*4882a593Smuzhiyun #include "mivalidate.h"
46*4882a593Smuzhiyun #include "validate.h"
47*4882a593Smuzhiyun #include "resource.h"
48*4882a593Smuzhiyun #include "gcstruct.h"
49*4882a593Smuzhiyun #include "dixstruct.h"
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun #include <X11/extensions/Xv.h>
52*4882a593Smuzhiyun #include <X11/extensions/Xvproto.h>
53*4882a593Smuzhiyun #include "xvdix.h"
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun #include "xf86xvpriv.h"
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun /* XvAdaptorRec fields */
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun static int xf86XVPutVideo(DrawablePtr, XvPortPtr, GCPtr,
60*4882a593Smuzhiyun                           INT16, INT16, CARD16, CARD16,
61*4882a593Smuzhiyun                           INT16, INT16, CARD16, CARD16);
62*4882a593Smuzhiyun static int xf86XVPutStill(DrawablePtr, XvPortPtr, GCPtr,
63*4882a593Smuzhiyun                           INT16, INT16, CARD16, CARD16,
64*4882a593Smuzhiyun                           INT16, INT16, CARD16, CARD16);
65*4882a593Smuzhiyun static int xf86XVGetVideo(DrawablePtr, XvPortPtr, GCPtr,
66*4882a593Smuzhiyun                           INT16, INT16, CARD16, CARD16,
67*4882a593Smuzhiyun                           INT16, INT16, CARD16, CARD16);
68*4882a593Smuzhiyun static int xf86XVGetStill(DrawablePtr, XvPortPtr, GCPtr,
69*4882a593Smuzhiyun                           INT16, INT16, CARD16, CARD16,
70*4882a593Smuzhiyun                           INT16, INT16, CARD16, CARD16);
71*4882a593Smuzhiyun static int xf86XVStopVideo(XvPortPtr, DrawablePtr);
72*4882a593Smuzhiyun static int xf86XVSetPortAttribute(XvPortPtr, Atom, INT32);
73*4882a593Smuzhiyun static int xf86XVGetPortAttribute(XvPortPtr, Atom, INT32 *);
74*4882a593Smuzhiyun static int xf86XVQueryBestSize(XvPortPtr, CARD8,
75*4882a593Smuzhiyun                                CARD16, CARD16, CARD16, CARD16,
76*4882a593Smuzhiyun                                unsigned int *, unsigned int *);
77*4882a593Smuzhiyun static int xf86XVPutImage(DrawablePtr, XvPortPtr, GCPtr,
78*4882a593Smuzhiyun                           INT16, INT16, CARD16, CARD16,
79*4882a593Smuzhiyun                           INT16, INT16, CARD16, CARD16,
80*4882a593Smuzhiyun                           XvImagePtr, unsigned char *, Bool, CARD16, CARD16);
81*4882a593Smuzhiyun static int xf86XVQueryImageAttributes(XvPortPtr, XvImagePtr,
82*4882a593Smuzhiyun                                       CARD16 *, CARD16 *, int *, int *);
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun /* ScreenRec fields */
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun static Bool xf86XVDestroyWindow(WindowPtr pWin);
87*4882a593Smuzhiyun static void xf86XVWindowExposures(WindowPtr pWin, RegionPtr r1);
88*4882a593Smuzhiyun static void xf86XVPostValidateTree(WindowPtr pWin, WindowPtr pLayerWin,
89*4882a593Smuzhiyun                                    VTKind kind);
90*4882a593Smuzhiyun static void xf86XVClipNotify(WindowPtr pWin, int dx, int dy);
91*4882a593Smuzhiyun static Bool xf86XVCloseScreen(ScreenPtr);
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun #define PostValidateTreeUndefined ((PostValidateTreeProcPtr)-1)
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun /* ScrnInfoRec functions */
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun static Bool xf86XVEnterVT(ScrnInfoPtr);
98*4882a593Smuzhiyun static void xf86XVLeaveVT(ScrnInfoPtr);
99*4882a593Smuzhiyun static void xf86XVAdjustFrame(ScrnInfoPtr, int x, int y);
100*4882a593Smuzhiyun static void xf86XVModeSet(ScrnInfoPtr pScrn);
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun /* misc */
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun static Bool xf86XVInitAdaptors(ScreenPtr, XF86VideoAdaptorPtr *, int);
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun static DevPrivateKeyRec XF86XVWindowKeyRec;
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun #define XF86XVWindowKey (&XF86XVWindowKeyRec)
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun /* dixmain.c XvScreenPtr screen private */
111*4882a593Smuzhiyun DevPrivateKey XF86XvScreenKey;
112*4882a593Smuzhiyun /** xf86xv.c XF86XVScreenPtr screen private */
113*4882a593Smuzhiyun static DevPrivateKeyRec XF86XVScreenPrivateKey;
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun static unsigned long PortResource = 0;
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun #define GET_XV_SCREEN(pScreen) \
118*4882a593Smuzhiyun     ((XvScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, XF86XvScreenKey))
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun #define GET_XF86XV_SCREEN(pScreen) \
121*4882a593Smuzhiyun     ((XF86XVScreenPtr)(dixGetPrivate(&pScreen->devPrivates, &XF86XVScreenPrivateKey)))
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun #define GET_XF86XV_WINDOW(pWin) \
124*4882a593Smuzhiyun     ((XF86XVWindowPtr)dixLookupPrivate(&(pWin)->devPrivates, XF86XVWindowKey))
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun static xf86XVInitGenericAdaptorPtr *GenDrivers = NULL;
127*4882a593Smuzhiyun static int NumGenDrivers = 0;
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun int
xf86XVRegisterGenericAdaptorDriver(xf86XVInitGenericAdaptorPtr InitFunc)130*4882a593Smuzhiyun xf86XVRegisterGenericAdaptorDriver(xf86XVInitGenericAdaptorPtr InitFunc)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun     xf86XVInitGenericAdaptorPtr *newdrivers;
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun     newdrivers = reallocarray(GenDrivers, 1 + NumGenDrivers,
135*4882a593Smuzhiyun                               sizeof(xf86XVInitGenericAdaptorPtr));
136*4882a593Smuzhiyun     if (!newdrivers)
137*4882a593Smuzhiyun         return 0;
138*4882a593Smuzhiyun     GenDrivers = newdrivers;
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun     GenDrivers[NumGenDrivers++] = InitFunc;
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun     return 1;
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun int
xf86XVListGenericAdaptors(ScrnInfoPtr pScrn,XF86VideoAdaptorPtr ** adaptors)146*4882a593Smuzhiyun xf86XVListGenericAdaptors(ScrnInfoPtr pScrn, XF86VideoAdaptorPtr ** adaptors)
147*4882a593Smuzhiyun {
148*4882a593Smuzhiyun     int i, j, n, num;
149*4882a593Smuzhiyun     XF86VideoAdaptorPtr *DrivAdap, *new;
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun     num = 0;
152*4882a593Smuzhiyun     *adaptors = NULL;
153*4882a593Smuzhiyun     /*
154*4882a593Smuzhiyun      * The v4l driver registers itself first, but can use surfaces registered
155*4882a593Smuzhiyun      * by other drivers.  So, call the v4l driver last.
156*4882a593Smuzhiyun      */
157*4882a593Smuzhiyun     for (i = NumGenDrivers; --i >= 0;) {
158*4882a593Smuzhiyun         DrivAdap = NULL;
159*4882a593Smuzhiyun         n = (*GenDrivers[i]) (pScrn, &DrivAdap);
160*4882a593Smuzhiyun         if (0 == n)
161*4882a593Smuzhiyun             continue;
162*4882a593Smuzhiyun         new = reallocarray(*adaptors, num + n, sizeof(XF86VideoAdaptorPtr));
163*4882a593Smuzhiyun         if (NULL == new)
164*4882a593Smuzhiyun             continue;
165*4882a593Smuzhiyun         *adaptors = new;
166*4882a593Smuzhiyun         for (j = 0; j < n; j++, num++)
167*4882a593Smuzhiyun             (*adaptors)[num] = DrivAdap[j];
168*4882a593Smuzhiyun     }
169*4882a593Smuzhiyun     return num;
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun /****************  Offscreen surface stuff *******************/
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun typedef struct {
175*4882a593Smuzhiyun     XF86OffscreenImagePtr images;
176*4882a593Smuzhiyun     int num;
177*4882a593Smuzhiyun } OffscreenImageRec;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun static DevPrivateKeyRec OffscreenPrivateKeyRec;
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun #define OffscreenPrivateKey (&OffscreenPrivateKeyRec)
182*4882a593Smuzhiyun #define GetOffscreenImage(pScreen) ((OffscreenImageRec *) dixLookupPrivate(&(pScreen)->devPrivates, OffscreenPrivateKey))
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun Bool
xf86XVRegisterOffscreenImages(ScreenPtr pScreen,XF86OffscreenImagePtr images,int num)185*4882a593Smuzhiyun xf86XVRegisterOffscreenImages(ScreenPtr pScreen,
186*4882a593Smuzhiyun                               XF86OffscreenImagePtr images, int num)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun     OffscreenImageRec *OffscreenImage;
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun     /* This function may be called before xf86XVScreenInit, so there's
191*4882a593Smuzhiyun      * no better place than this to call dixRegisterPrivateKey to ensure we
192*4882a593Smuzhiyun      * have space reserved. After the first call it is a no-op. */
193*4882a593Smuzhiyun     if (!dixRegisterPrivateKey
194*4882a593Smuzhiyun         (OffscreenPrivateKey, PRIVATE_SCREEN, sizeof(OffscreenImageRec)) ||
195*4882a593Smuzhiyun         !(OffscreenImage = GetOffscreenImage(pScreen)))
196*4882a593Smuzhiyun         /* Every X.org driver assumes this function always succeeds, so
197*4882a593Smuzhiyun          * just die on allocation failure. */
198*4882a593Smuzhiyun         FatalError
199*4882a593Smuzhiyun             ("Could not allocate private storage for XV offscreen images.\n");
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun     OffscreenImage->num = num;
202*4882a593Smuzhiyun     OffscreenImage->images = images;
203*4882a593Smuzhiyun     return TRUE;
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun XF86OffscreenImagePtr
xf86XVQueryOffscreenImages(ScreenPtr pScreen,int * num)207*4882a593Smuzhiyun xf86XVQueryOffscreenImages(ScreenPtr pScreen, int *num)
208*4882a593Smuzhiyun {
209*4882a593Smuzhiyun     OffscreenImageRec *OffscreenImage = GetOffscreenImage(pScreen);
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun     *num = OffscreenImage->num;
212*4882a593Smuzhiyun     return OffscreenImage->images;
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun XF86VideoAdaptorPtr
xf86XVAllocateVideoAdaptorRec(ScrnInfoPtr pScrn)216*4882a593Smuzhiyun xf86XVAllocateVideoAdaptorRec(ScrnInfoPtr pScrn)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun     return calloc(1, sizeof(XF86VideoAdaptorRec));
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun void
xf86XVFreeVideoAdaptorRec(XF86VideoAdaptorPtr ptr)222*4882a593Smuzhiyun xf86XVFreeVideoAdaptorRec(XF86VideoAdaptorPtr ptr)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun     free(ptr);
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun Bool
xf86XVScreenInit(ScreenPtr pScreen,XF86VideoAdaptorPtr * adaptors,int num)228*4882a593Smuzhiyun xf86XVScreenInit(ScreenPtr pScreen, XF86VideoAdaptorPtr * adaptors, int num)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun     ScrnInfoPtr pScrn;
231*4882a593Smuzhiyun     XF86XVScreenPtr ScreenPriv;
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun     if (num <= 0 || noXvExtension)
234*4882a593Smuzhiyun         return FALSE;
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun     if (Success != XvScreenInit(pScreen))
237*4882a593Smuzhiyun         return FALSE;
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun     if (!dixRegisterPrivateKey(&XF86XVWindowKeyRec, PRIVATE_WINDOW, 0))
240*4882a593Smuzhiyun         return FALSE;
241*4882a593Smuzhiyun     if (!dixRegisterPrivateKey(&XF86XVScreenPrivateKey, PRIVATE_SCREEN, 0))
242*4882a593Smuzhiyun         return FALSE;
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun     XF86XvScreenKey = XvGetScreenKey();
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun     PortResource = XvGetRTPort();
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun     ScreenPriv = malloc(sizeof(XF86XVScreenRec));
249*4882a593Smuzhiyun     dixSetPrivate(&pScreen->devPrivates, &XF86XVScreenPrivateKey, ScreenPriv);
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun     if (!ScreenPriv)
252*4882a593Smuzhiyun         return FALSE;
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun     pScrn = xf86ScreenToScrn(pScreen);
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun     ScreenPriv->DestroyWindow = pScreen->DestroyWindow;
257*4882a593Smuzhiyun     ScreenPriv->WindowExposures = pScreen->WindowExposures;
258*4882a593Smuzhiyun     ScreenPriv->PostValidateTree = PostValidateTreeUndefined;
259*4882a593Smuzhiyun     ScreenPriv->ClipNotify = pScreen->ClipNotify;
260*4882a593Smuzhiyun     ScreenPriv->CloseScreen = pScreen->CloseScreen;
261*4882a593Smuzhiyun     ScreenPriv->EnterVT = pScrn->EnterVT;
262*4882a593Smuzhiyun     ScreenPriv->LeaveVT = pScrn->LeaveVT;
263*4882a593Smuzhiyun     ScreenPriv->AdjustFrame = pScrn->AdjustFrame;
264*4882a593Smuzhiyun     ScreenPriv->ModeSet = pScrn->ModeSet;
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun     pScreen->DestroyWindow = xf86XVDestroyWindow;
267*4882a593Smuzhiyun     pScreen->WindowExposures = xf86XVWindowExposures;
268*4882a593Smuzhiyun     pScreen->ClipNotify = xf86XVClipNotify;
269*4882a593Smuzhiyun     pScreen->CloseScreen = xf86XVCloseScreen;
270*4882a593Smuzhiyun     pScrn->EnterVT = xf86XVEnterVT;
271*4882a593Smuzhiyun     pScrn->LeaveVT = xf86XVLeaveVT;
272*4882a593Smuzhiyun     if (pScrn->AdjustFrame)
273*4882a593Smuzhiyun         pScrn->AdjustFrame = xf86XVAdjustFrame;
274*4882a593Smuzhiyun     pScrn->ModeSet = xf86XVModeSet;
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun     if (!xf86XVInitAdaptors(pScreen, adaptors, num))
277*4882a593Smuzhiyun         return FALSE;
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun     return TRUE;
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun static void
xf86XVFreeAdaptor(XvAdaptorPtr pAdaptor)283*4882a593Smuzhiyun xf86XVFreeAdaptor(XvAdaptorPtr pAdaptor)
284*4882a593Smuzhiyun {
285*4882a593Smuzhiyun     int i;
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun     if (pAdaptor->pPorts) {
288*4882a593Smuzhiyun         XvPortPtr pPort = pAdaptor->pPorts;
289*4882a593Smuzhiyun         XvPortRecPrivatePtr pPriv;
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun         for (i = 0; i < pAdaptor->nPorts; i++, pPort++) {
292*4882a593Smuzhiyun             pPriv = (XvPortRecPrivatePtr) pPort->devPriv.ptr;
293*4882a593Smuzhiyun             if (pPriv) {
294*4882a593Smuzhiyun                 if (pPriv->clientClip)
295*4882a593Smuzhiyun                     RegionDestroy(pPriv->clientClip);
296*4882a593Smuzhiyun                 if (pPriv->pCompositeClip && pPriv->FreeCompositeClip)
297*4882a593Smuzhiyun                     RegionDestroy(pPriv->pCompositeClip);
298*4882a593Smuzhiyun                 if (pPriv->ckeyFilled)
299*4882a593Smuzhiyun                     RegionDestroy(pPriv->ckeyFilled);
300*4882a593Smuzhiyun                 free(pPriv);
301*4882a593Smuzhiyun             }
302*4882a593Smuzhiyun         }
303*4882a593Smuzhiyun     }
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun     XvFreeAdaptor(pAdaptor);
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun static Bool
xf86XVInitAdaptors(ScreenPtr pScreen,XF86VideoAdaptorPtr * infoPtr,int number)309*4882a593Smuzhiyun xf86XVInitAdaptors(ScreenPtr pScreen, XF86VideoAdaptorPtr * infoPtr, int number)
310*4882a593Smuzhiyun {
311*4882a593Smuzhiyun     XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
312*4882a593Smuzhiyun     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
313*4882a593Smuzhiyun     XF86VideoAdaptorPtr adaptorPtr;
314*4882a593Smuzhiyun     XvAdaptorPtr pAdaptor, pa;
315*4882a593Smuzhiyun     XvAdaptorRecPrivatePtr adaptorPriv;
316*4882a593Smuzhiyun     int na, numAdaptor;
317*4882a593Smuzhiyun     XvPortRecPrivatePtr portPriv;
318*4882a593Smuzhiyun     XvPortPtr pPort, pp;
319*4882a593Smuzhiyun     int numPort;
320*4882a593Smuzhiyun     XF86VideoFormatPtr formatPtr;
321*4882a593Smuzhiyun     XvFormatPtr pFormat, pf;
322*4882a593Smuzhiyun     int numFormat, totFormat;
323*4882a593Smuzhiyun     XF86VideoEncodingPtr encodingPtr;
324*4882a593Smuzhiyun     XvEncodingPtr pEncode, pe;
325*4882a593Smuzhiyun     int numVisuals;
326*4882a593Smuzhiyun     VisualPtr pVisual;
327*4882a593Smuzhiyun     int i;
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun     pxvs->nAdaptors = 0;
330*4882a593Smuzhiyun     pxvs->pAdaptors = NULL;
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun     if (!(pAdaptor = calloc(number, sizeof(XvAdaptorRec))))
333*4882a593Smuzhiyun         return FALSE;
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun     for (pa = pAdaptor, na = 0, numAdaptor = 0; na < number; na++, adaptorPtr++) {
336*4882a593Smuzhiyun         adaptorPtr = infoPtr[na];
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun         if (!adaptorPtr->StopVideo || !adaptorPtr->SetPortAttribute ||
339*4882a593Smuzhiyun             !adaptorPtr->GetPortAttribute || !adaptorPtr->QueryBestSize)
340*4882a593Smuzhiyun             continue;
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun         /* client libs expect at least one encoding */
343*4882a593Smuzhiyun         if (!adaptorPtr->nEncodings || !adaptorPtr->pEncodings)
344*4882a593Smuzhiyun             continue;
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun         pa->type = adaptorPtr->type;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun         if (!adaptorPtr->PutVideo && !adaptorPtr->GetVideo)
349*4882a593Smuzhiyun             pa->type &= ~XvVideoMask;
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun         if (!adaptorPtr->PutStill && !adaptorPtr->GetStill)
352*4882a593Smuzhiyun             pa->type &= ~XvStillMask;
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun         if (!adaptorPtr->PutImage || !adaptorPtr->QueryImageAttributes)
355*4882a593Smuzhiyun             pa->type &= ~XvImageMask;
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun         if (!adaptorPtr->PutVideo && !adaptorPtr->PutImage &&
358*4882a593Smuzhiyun             !adaptorPtr->PutStill)
359*4882a593Smuzhiyun             pa->type &= ~XvInputMask;
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun         if (!adaptorPtr->GetVideo && !adaptorPtr->GetStill)
362*4882a593Smuzhiyun             pa->type &= ~XvOutputMask;
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun         if (!(adaptorPtr->type & (XvPixmapMask | XvWindowMask)))
365*4882a593Smuzhiyun             continue;
366*4882a593Smuzhiyun         if (!(adaptorPtr->type & (XvImageMask | XvVideoMask | XvStillMask)))
367*4882a593Smuzhiyun             continue;
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun         pa->pScreen = pScreen;
370*4882a593Smuzhiyun         pa->ddPutVideo = xf86XVPutVideo;
371*4882a593Smuzhiyun         pa->ddPutStill = xf86XVPutStill;
372*4882a593Smuzhiyun         pa->ddGetVideo = xf86XVGetVideo;
373*4882a593Smuzhiyun         pa->ddGetStill = xf86XVGetStill;
374*4882a593Smuzhiyun         pa->ddStopVideo = xf86XVStopVideo;
375*4882a593Smuzhiyun         pa->ddPutImage = xf86XVPutImage;
376*4882a593Smuzhiyun         pa->ddSetPortAttribute = xf86XVSetPortAttribute;
377*4882a593Smuzhiyun         pa->ddGetPortAttribute = xf86XVGetPortAttribute;
378*4882a593Smuzhiyun         pa->ddQueryBestSize = xf86XVQueryBestSize;
379*4882a593Smuzhiyun         pa->ddQueryImageAttributes = xf86XVQueryImageAttributes;
380*4882a593Smuzhiyun         pa->name = strdup(adaptorPtr->name);
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun         if (adaptorPtr->nEncodings &&
383*4882a593Smuzhiyun             (pEncode = calloc(adaptorPtr->nEncodings, sizeof(XvEncodingRec)))) {
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun             for (pe = pEncode, encodingPtr = adaptorPtr->pEncodings, i = 0;
386*4882a593Smuzhiyun                  i < adaptorPtr->nEncodings; pe++, i++, encodingPtr++) {
387*4882a593Smuzhiyun                 pe->id = encodingPtr->id;
388*4882a593Smuzhiyun                 pe->pScreen = pScreen;
389*4882a593Smuzhiyun                 pe->name = strdup(encodingPtr->name);
390*4882a593Smuzhiyun                 pe->width = encodingPtr->width;
391*4882a593Smuzhiyun                 pe->height = encodingPtr->height;
392*4882a593Smuzhiyun                 pe->rate.numerator = encodingPtr->rate.numerator;
393*4882a593Smuzhiyun                 pe->rate.denominator = encodingPtr->rate.denominator;
394*4882a593Smuzhiyun             }
395*4882a593Smuzhiyun             pa->nEncodings = adaptorPtr->nEncodings;
396*4882a593Smuzhiyun             pa->pEncodings = pEncode;
397*4882a593Smuzhiyun         }
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun         if (adaptorPtr->nImages &&
400*4882a593Smuzhiyun             (pa->pImages = calloc(adaptorPtr->nImages, sizeof(XvImageRec)))) {
401*4882a593Smuzhiyun             memcpy(pa->pImages, adaptorPtr->pImages,
402*4882a593Smuzhiyun                    adaptorPtr->nImages * sizeof(XvImageRec));
403*4882a593Smuzhiyun             pa->nImages = adaptorPtr->nImages;
404*4882a593Smuzhiyun         }
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun         if (adaptorPtr->nAttributes &&
407*4882a593Smuzhiyun             (pa->pAttributes = calloc(adaptorPtr->nAttributes,
408*4882a593Smuzhiyun                                       sizeof(XvAttributeRec)))) {
409*4882a593Smuzhiyun             memcpy(pa->pAttributes, adaptorPtr->pAttributes,
410*4882a593Smuzhiyun                    adaptorPtr->nAttributes * sizeof(XvAttributeRec));
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun             for (i = 0; i < adaptorPtr->nAttributes; i++) {
413*4882a593Smuzhiyun                 pa->pAttributes[i].name =
414*4882a593Smuzhiyun                     strdup(adaptorPtr->pAttributes[i].name);
415*4882a593Smuzhiyun             }
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun             pa->nAttributes = adaptorPtr->nAttributes;
418*4882a593Smuzhiyun         }
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun         totFormat = adaptorPtr->nFormats;
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun         if (!(pFormat = calloc(totFormat, sizeof(XvFormatRec)))) {
423*4882a593Smuzhiyun             xf86XVFreeAdaptor(pa);
424*4882a593Smuzhiyun             continue;
425*4882a593Smuzhiyun         }
426*4882a593Smuzhiyun         for (pf = pFormat, i = 0, numFormat = 0, formatPtr =
427*4882a593Smuzhiyun              adaptorPtr->pFormats; i < adaptorPtr->nFormats; i++, formatPtr++) {
428*4882a593Smuzhiyun             numVisuals = pScreen->numVisuals;
429*4882a593Smuzhiyun             pVisual = pScreen->visuals;
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun             while (numVisuals--) {
432*4882a593Smuzhiyun                 if ((pVisual->class == formatPtr->class) &&
433*4882a593Smuzhiyun                     (pVisual->nplanes == formatPtr->depth)) {
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun                     if (numFormat >= totFormat) {
436*4882a593Smuzhiyun                         void *moreSpace;
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun                         totFormat *= 2;
439*4882a593Smuzhiyun                         moreSpace = reallocarray(pFormat, totFormat,
440*4882a593Smuzhiyun                                                  sizeof(XvFormatRec));
441*4882a593Smuzhiyun                         if (!moreSpace)
442*4882a593Smuzhiyun                             break;
443*4882a593Smuzhiyun                         pFormat = moreSpace;
444*4882a593Smuzhiyun                         pf = pFormat + numFormat;
445*4882a593Smuzhiyun                     }
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun                     pf->visual = pVisual->vid;
448*4882a593Smuzhiyun                     pf->depth = formatPtr->depth;
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun                     pf++;
451*4882a593Smuzhiyun                     numFormat++;
452*4882a593Smuzhiyun                 }
453*4882a593Smuzhiyun                 pVisual++;
454*4882a593Smuzhiyun             }
455*4882a593Smuzhiyun         }
456*4882a593Smuzhiyun         pa->nFormats = numFormat;
457*4882a593Smuzhiyun         pa->pFormats = pFormat;
458*4882a593Smuzhiyun         if (!numFormat) {
459*4882a593Smuzhiyun             xf86XVFreeAdaptor(pa);
460*4882a593Smuzhiyun             continue;
461*4882a593Smuzhiyun         }
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun         if (!(adaptorPriv = calloc(1, sizeof(XvAdaptorRecPrivate)))) {
464*4882a593Smuzhiyun             xf86XVFreeAdaptor(pa);
465*4882a593Smuzhiyun             continue;
466*4882a593Smuzhiyun         }
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun         adaptorPriv->flags = adaptorPtr->flags;
469*4882a593Smuzhiyun         adaptorPriv->PutVideo = adaptorPtr->PutVideo;
470*4882a593Smuzhiyun         adaptorPriv->PutStill = adaptorPtr->PutStill;
471*4882a593Smuzhiyun         adaptorPriv->GetVideo = adaptorPtr->GetVideo;
472*4882a593Smuzhiyun         adaptorPriv->GetStill = adaptorPtr->GetStill;
473*4882a593Smuzhiyun         adaptorPriv->StopVideo = adaptorPtr->StopVideo;
474*4882a593Smuzhiyun         adaptorPriv->SetPortAttribute = adaptorPtr->SetPortAttribute;
475*4882a593Smuzhiyun         adaptorPriv->GetPortAttribute = adaptorPtr->GetPortAttribute;
476*4882a593Smuzhiyun         adaptorPriv->QueryBestSize = adaptorPtr->QueryBestSize;
477*4882a593Smuzhiyun         adaptorPriv->QueryImageAttributes = adaptorPtr->QueryImageAttributes;
478*4882a593Smuzhiyun         adaptorPriv->PutImage = adaptorPtr->PutImage;
479*4882a593Smuzhiyun         adaptorPriv->ReputImage = adaptorPtr->ReputImage;       /* image/still */
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun         pa->devPriv.ptr = (void *) adaptorPriv;
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun         if (!(pPort = calloc(adaptorPtr->nPorts, sizeof(XvPortRec)))) {
484*4882a593Smuzhiyun             xf86XVFreeAdaptor(pa);
485*4882a593Smuzhiyun             continue;
486*4882a593Smuzhiyun         }
487*4882a593Smuzhiyun         for (pp = pPort, i = 0, numPort = 0; i < adaptorPtr->nPorts; i++) {
488*4882a593Smuzhiyun 
489*4882a593Smuzhiyun             if (!(pp->id = FakeClientID(0)))
490*4882a593Smuzhiyun                 continue;
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun             if (!(portPriv = calloc(1, sizeof(XvPortRecPrivate))))
493*4882a593Smuzhiyun                 continue;
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun             if (!AddResource(pp->id, PortResource, pp)) {
496*4882a593Smuzhiyun                 free(portPriv);
497*4882a593Smuzhiyun                 continue;
498*4882a593Smuzhiyun             }
499*4882a593Smuzhiyun 
500*4882a593Smuzhiyun             pp->pAdaptor = pa;
501*4882a593Smuzhiyun             pp->pNotify = (XvPortNotifyPtr) NULL;
502*4882a593Smuzhiyun             pp->pDraw = (DrawablePtr) NULL;
503*4882a593Smuzhiyun             pp->client = (ClientPtr) NULL;
504*4882a593Smuzhiyun             pp->grab.client = (ClientPtr) NULL;
505*4882a593Smuzhiyun             pp->time = currentTime;
506*4882a593Smuzhiyun             pp->devPriv.ptr = portPriv;
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun             portPriv->pScrn = pScrn;
509*4882a593Smuzhiyun             portPriv->AdaptorRec = adaptorPriv;
510*4882a593Smuzhiyun             portPriv->DevPriv.ptr = adaptorPtr->pPortPrivates[i].ptr;
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun             pp++;
513*4882a593Smuzhiyun             numPort++;
514*4882a593Smuzhiyun         }
515*4882a593Smuzhiyun         pa->nPorts = numPort;
516*4882a593Smuzhiyun         pa->pPorts = pPort;
517*4882a593Smuzhiyun         if (!numPort) {
518*4882a593Smuzhiyun             xf86XVFreeAdaptor(pa);
519*4882a593Smuzhiyun             continue;
520*4882a593Smuzhiyun         }
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun         pa->base_id = pPort->id;
523*4882a593Smuzhiyun 
524*4882a593Smuzhiyun         pa++;
525*4882a593Smuzhiyun         numAdaptor++;
526*4882a593Smuzhiyun     }
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun     if (numAdaptor) {
529*4882a593Smuzhiyun         pxvs->nAdaptors = numAdaptor;
530*4882a593Smuzhiyun         pxvs->pAdaptors = pAdaptor;
531*4882a593Smuzhiyun     }
532*4882a593Smuzhiyun     else {
533*4882a593Smuzhiyun         free(pAdaptor);
534*4882a593Smuzhiyun         return FALSE;
535*4882a593Smuzhiyun     }
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun     return TRUE;
538*4882a593Smuzhiyun }
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun /* Video should be clipped to the intersection of the window cliplist
541*4882a593Smuzhiyun    and the client cliplist specified in the GC for which the video was
542*4882a593Smuzhiyun    initialized.  When we need to reclip a window, the GC that started
543*4882a593Smuzhiyun    the video may not even be around anymore.  That's why we save the
544*4882a593Smuzhiyun    client clip from the GC when the video is initialized.  We then
545*4882a593Smuzhiyun    use xf86XVUpdateCompositeClip to calculate the new composite clip
546*4882a593Smuzhiyun    when we need it.  This is different from what DEC did.  They saved
547*4882a593Smuzhiyun    the GC and used it's clip list when they needed to reclip the window,
548*4882a593Smuzhiyun    even if the client clip was different from the one the video was
549*4882a593Smuzhiyun    initialized with.  If the original GC was destroyed, they had to stop
550*4882a593Smuzhiyun    the video.  I like the new method better (MArk).
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun    This function only works for windows.  Will need to rewrite when
553*4882a593Smuzhiyun    (if) we support pixmap rendering.
554*4882a593Smuzhiyun */
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun static void
xf86XVUpdateCompositeClip(XvPortRecPrivatePtr portPriv)557*4882a593Smuzhiyun xf86XVUpdateCompositeClip(XvPortRecPrivatePtr portPriv)
558*4882a593Smuzhiyun {
559*4882a593Smuzhiyun     RegionPtr pregWin, pCompositeClip;
560*4882a593Smuzhiyun     WindowPtr pWin;
561*4882a593Smuzhiyun     Bool freeCompClip = FALSE;
562*4882a593Smuzhiyun 
563*4882a593Smuzhiyun     if (portPriv->pCompositeClip)
564*4882a593Smuzhiyun         return;
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun     pWin = (WindowPtr) portPriv->pDraw;
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun     /* get window clip list */
569*4882a593Smuzhiyun     if (portPriv->subWindowMode == IncludeInferiors) {
570*4882a593Smuzhiyun         pregWin = NotClippedByChildren(pWin);
571*4882a593Smuzhiyun         freeCompClip = TRUE;
572*4882a593Smuzhiyun     }
573*4882a593Smuzhiyun     else
574*4882a593Smuzhiyun         pregWin = &pWin->clipList;
575*4882a593Smuzhiyun 
576*4882a593Smuzhiyun     if (!portPriv->clientClip) {
577*4882a593Smuzhiyun         portPriv->pCompositeClip = pregWin;
578*4882a593Smuzhiyun         portPriv->FreeCompositeClip = freeCompClip;
579*4882a593Smuzhiyun         return;
580*4882a593Smuzhiyun     }
581*4882a593Smuzhiyun 
582*4882a593Smuzhiyun     pCompositeClip = RegionCreate(NullBox, 1);
583*4882a593Smuzhiyun     RegionCopy(pCompositeClip, portPriv->clientClip);
584*4882a593Smuzhiyun     RegionTranslate(pCompositeClip, portPriv->pDraw->x, portPriv->pDraw->y);
585*4882a593Smuzhiyun     RegionIntersect(pCompositeClip, pregWin, pCompositeClip);
586*4882a593Smuzhiyun 
587*4882a593Smuzhiyun     portPriv->pCompositeClip = pCompositeClip;
588*4882a593Smuzhiyun     portPriv->FreeCompositeClip = TRUE;
589*4882a593Smuzhiyun 
590*4882a593Smuzhiyun     if (freeCompClip) {
591*4882a593Smuzhiyun         RegionDestroy(pregWin);
592*4882a593Smuzhiyun     }
593*4882a593Smuzhiyun }
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun /* Save the current clientClip and update the CompositeClip whenever
596*4882a593Smuzhiyun    we have a fresh GC */
597*4882a593Smuzhiyun 
598*4882a593Smuzhiyun static void
xf86XVCopyClip(XvPortRecPrivatePtr portPriv,GCPtr pGC)599*4882a593Smuzhiyun xf86XVCopyClip(XvPortRecPrivatePtr portPriv, GCPtr pGC)
600*4882a593Smuzhiyun {
601*4882a593Smuzhiyun     /* copy the new clip if it exists */
602*4882a593Smuzhiyun     if (pGC->clientClip) {
603*4882a593Smuzhiyun         if (!portPriv->clientClip)
604*4882a593Smuzhiyun             portPriv->clientClip = RegionCreate(NullBox, 1);
605*4882a593Smuzhiyun         /* Note: this is in window coordinates */
606*4882a593Smuzhiyun         RegionCopy(portPriv->clientClip, pGC->clientClip);
607*4882a593Smuzhiyun         RegionTranslate(portPriv->clientClip, pGC->clipOrg.x, pGC->clipOrg.y);
608*4882a593Smuzhiyun     }
609*4882a593Smuzhiyun     else if (portPriv->clientClip) {    /* free the old clientClip */
610*4882a593Smuzhiyun         RegionDestroy(portPriv->clientClip);
611*4882a593Smuzhiyun         portPriv->clientClip = NULL;
612*4882a593Smuzhiyun     }
613*4882a593Smuzhiyun 
614*4882a593Smuzhiyun     /* get rid of the old clip list */
615*4882a593Smuzhiyun     if (portPriv->pCompositeClip && portPriv->FreeCompositeClip) {
616*4882a593Smuzhiyun         RegionDestroy(portPriv->pCompositeClip);
617*4882a593Smuzhiyun     }
618*4882a593Smuzhiyun 
619*4882a593Smuzhiyun     portPriv->pCompositeClip = pGC->pCompositeClip;
620*4882a593Smuzhiyun     portPriv->FreeCompositeClip = FALSE;
621*4882a593Smuzhiyun     portPriv->subWindowMode = pGC->subWindowMode;
622*4882a593Smuzhiyun }
623*4882a593Smuzhiyun 
624*4882a593Smuzhiyun static void
xf86XVCopyCompositeClip(XvPortRecPrivatePtr portPriv,GCPtr pGC,DrawablePtr pDraw)625*4882a593Smuzhiyun xf86XVCopyCompositeClip(XvPortRecPrivatePtr portPriv,
626*4882a593Smuzhiyun                         GCPtr pGC, DrawablePtr pDraw)
627*4882a593Smuzhiyun {
628*4882a593Smuzhiyun     if (!portPriv->clientClip)
629*4882a593Smuzhiyun         portPriv->clientClip = RegionCreate(NullBox, 1);
630*4882a593Smuzhiyun     /* Keep the original GC composite clip around for ReputImage */
631*4882a593Smuzhiyun     RegionCopy(portPriv->clientClip, pGC->pCompositeClip);
632*4882a593Smuzhiyun     RegionTranslate(portPriv->clientClip, -pDraw->x, -pDraw->y);
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun     /* get rid of the old clip list */
635*4882a593Smuzhiyun     if (portPriv->pCompositeClip && portPriv->FreeCompositeClip)
636*4882a593Smuzhiyun         RegionDestroy(portPriv->pCompositeClip);
637*4882a593Smuzhiyun 
638*4882a593Smuzhiyun     portPriv->pCompositeClip = pGC->pCompositeClip;
639*4882a593Smuzhiyun     portPriv->FreeCompositeClip = FALSE;
640*4882a593Smuzhiyun     portPriv->subWindowMode = pGC->subWindowMode;
641*4882a593Smuzhiyun }
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun static int
xf86XVRegetVideo(XvPortRecPrivatePtr portPriv)644*4882a593Smuzhiyun xf86XVRegetVideo(XvPortRecPrivatePtr portPriv)
645*4882a593Smuzhiyun {
646*4882a593Smuzhiyun     RegionRec WinRegion;
647*4882a593Smuzhiyun     RegionRec ClipRegion;
648*4882a593Smuzhiyun     BoxRec WinBox;
649*4882a593Smuzhiyun     int ret = Success;
650*4882a593Smuzhiyun     Bool clippedAway = FALSE;
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun     xf86XVUpdateCompositeClip(portPriv);
653*4882a593Smuzhiyun 
654*4882a593Smuzhiyun     /* translate the video region to the screen */
655*4882a593Smuzhiyun     WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
656*4882a593Smuzhiyun     WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
657*4882a593Smuzhiyun     WinBox.x2 = WinBox.x1 + portPriv->drw_w;
658*4882a593Smuzhiyun     WinBox.y2 = WinBox.y1 + portPriv->drw_h;
659*4882a593Smuzhiyun 
660*4882a593Smuzhiyun     /* clip to the window composite clip */
661*4882a593Smuzhiyun     RegionInit(&WinRegion, &WinBox, 1);
662*4882a593Smuzhiyun     RegionNull(&ClipRegion);
663*4882a593Smuzhiyun     RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
664*4882a593Smuzhiyun 
665*4882a593Smuzhiyun     /* that's all if it's totally obscured */
666*4882a593Smuzhiyun     if (!RegionNotEmpty(&ClipRegion)) {
667*4882a593Smuzhiyun         clippedAway = TRUE;
668*4882a593Smuzhiyun         goto CLIP_VIDEO_BAILOUT;
669*4882a593Smuzhiyun     }
670*4882a593Smuzhiyun 
671*4882a593Smuzhiyun     ret = (*portPriv->AdaptorRec->GetVideo) (portPriv->pScrn,
672*4882a593Smuzhiyun                                              portPriv->vid_x, portPriv->vid_y,
673*4882a593Smuzhiyun                                              WinBox.x1, WinBox.y1,
674*4882a593Smuzhiyun                                              portPriv->vid_w, portPriv->vid_h,
675*4882a593Smuzhiyun                                              portPriv->drw_w, portPriv->drw_h,
676*4882a593Smuzhiyun                                              &ClipRegion, portPriv->DevPriv.ptr,
677*4882a593Smuzhiyun                                              portPriv->pDraw);
678*4882a593Smuzhiyun 
679*4882a593Smuzhiyun     if (ret == Success)
680*4882a593Smuzhiyun         portPriv->isOn = XV_ON;
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun  CLIP_VIDEO_BAILOUT:
683*4882a593Smuzhiyun 
684*4882a593Smuzhiyun     if ((clippedAway || (ret != Success)) && portPriv->isOn == XV_ON) {
685*4882a593Smuzhiyun         (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
686*4882a593Smuzhiyun                                             portPriv->DevPriv.ptr, FALSE);
687*4882a593Smuzhiyun         portPriv->isOn = XV_PENDING;
688*4882a593Smuzhiyun     }
689*4882a593Smuzhiyun 
690*4882a593Smuzhiyun     /* This clip was copied and only good for one shot */
691*4882a593Smuzhiyun     if (!portPriv->FreeCompositeClip)
692*4882a593Smuzhiyun         portPriv->pCompositeClip = NULL;
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun     RegionUninit(&WinRegion);
695*4882a593Smuzhiyun     RegionUninit(&ClipRegion);
696*4882a593Smuzhiyun 
697*4882a593Smuzhiyun     return ret;
698*4882a593Smuzhiyun }
699*4882a593Smuzhiyun 
700*4882a593Smuzhiyun static int
xf86XVReputVideo(XvPortRecPrivatePtr portPriv)701*4882a593Smuzhiyun xf86XVReputVideo(XvPortRecPrivatePtr portPriv)
702*4882a593Smuzhiyun {
703*4882a593Smuzhiyun     RegionRec WinRegion;
704*4882a593Smuzhiyun     RegionRec ClipRegion;
705*4882a593Smuzhiyun     BoxRec WinBox;
706*4882a593Smuzhiyun     int ret = Success;
707*4882a593Smuzhiyun     Bool clippedAway = FALSE;
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun     xf86XVUpdateCompositeClip(portPriv);
710*4882a593Smuzhiyun 
711*4882a593Smuzhiyun     /* translate the video region to the screen */
712*4882a593Smuzhiyun     WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
713*4882a593Smuzhiyun     WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
714*4882a593Smuzhiyun     WinBox.x2 = WinBox.x1 + portPriv->drw_w;
715*4882a593Smuzhiyun     WinBox.y2 = WinBox.y1 + portPriv->drw_h;
716*4882a593Smuzhiyun 
717*4882a593Smuzhiyun     /* clip to the window composite clip */
718*4882a593Smuzhiyun     RegionInit(&WinRegion, &WinBox, 1);
719*4882a593Smuzhiyun     RegionNull(&ClipRegion);
720*4882a593Smuzhiyun     RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
721*4882a593Smuzhiyun 
722*4882a593Smuzhiyun     /* clip and translate to the viewport */
723*4882a593Smuzhiyun     if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
724*4882a593Smuzhiyun         RegionRec VPReg;
725*4882a593Smuzhiyun         BoxRec VPBox;
726*4882a593Smuzhiyun 
727*4882a593Smuzhiyun         VPBox.x1 = portPriv->pScrn->frameX0;
728*4882a593Smuzhiyun         VPBox.y1 = portPriv->pScrn->frameY0;
729*4882a593Smuzhiyun         VPBox.x2 = portPriv->pScrn->frameX1 + 1;
730*4882a593Smuzhiyun         VPBox.y2 = portPriv->pScrn->frameY1 + 1;
731*4882a593Smuzhiyun 
732*4882a593Smuzhiyun         RegionInit(&VPReg, &VPBox, 1);
733*4882a593Smuzhiyun         RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
734*4882a593Smuzhiyun         RegionUninit(&VPReg);
735*4882a593Smuzhiyun     }
736*4882a593Smuzhiyun 
737*4882a593Smuzhiyun     /* that's all if it's totally obscured */
738*4882a593Smuzhiyun     if (!RegionNotEmpty(&ClipRegion)) {
739*4882a593Smuzhiyun         clippedAway = TRUE;
740*4882a593Smuzhiyun         goto CLIP_VIDEO_BAILOUT;
741*4882a593Smuzhiyun     }
742*4882a593Smuzhiyun 
743*4882a593Smuzhiyun     ret = (*portPriv->AdaptorRec->PutVideo) (portPriv->pScrn,
744*4882a593Smuzhiyun                                              portPriv->vid_x, portPriv->vid_y,
745*4882a593Smuzhiyun                                              WinBox.x1, WinBox.y1,
746*4882a593Smuzhiyun                                              portPriv->vid_w, portPriv->vid_h,
747*4882a593Smuzhiyun                                              portPriv->drw_w, portPriv->drw_h,
748*4882a593Smuzhiyun                                              &ClipRegion, portPriv->DevPriv.ptr,
749*4882a593Smuzhiyun                                              portPriv->pDraw);
750*4882a593Smuzhiyun 
751*4882a593Smuzhiyun     if (ret == Success)
752*4882a593Smuzhiyun         portPriv->isOn = XV_ON;
753*4882a593Smuzhiyun 
754*4882a593Smuzhiyun  CLIP_VIDEO_BAILOUT:
755*4882a593Smuzhiyun 
756*4882a593Smuzhiyun     if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
757*4882a593Smuzhiyun         (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
758*4882a593Smuzhiyun                                             portPriv->DevPriv.ptr, FALSE);
759*4882a593Smuzhiyun         portPriv->isOn = XV_PENDING;
760*4882a593Smuzhiyun     }
761*4882a593Smuzhiyun 
762*4882a593Smuzhiyun     /* This clip was copied and only good for one shot */
763*4882a593Smuzhiyun     if (!portPriv->FreeCompositeClip)
764*4882a593Smuzhiyun         portPriv->pCompositeClip = NULL;
765*4882a593Smuzhiyun 
766*4882a593Smuzhiyun     RegionUninit(&WinRegion);
767*4882a593Smuzhiyun     RegionUninit(&ClipRegion);
768*4882a593Smuzhiyun 
769*4882a593Smuzhiyun     return ret;
770*4882a593Smuzhiyun }
771*4882a593Smuzhiyun 
772*4882a593Smuzhiyun /* Reput image/still */
773*4882a593Smuzhiyun static int
xf86XVReputImage(XvPortRecPrivatePtr portPriv)774*4882a593Smuzhiyun xf86XVReputImage(XvPortRecPrivatePtr portPriv)
775*4882a593Smuzhiyun {
776*4882a593Smuzhiyun     RegionRec WinRegion;
777*4882a593Smuzhiyun     RegionRec ClipRegion;
778*4882a593Smuzhiyun     BoxRec WinBox;
779*4882a593Smuzhiyun     int ret = Success;
780*4882a593Smuzhiyun     Bool clippedAway = FALSE;
781*4882a593Smuzhiyun 
782*4882a593Smuzhiyun     xf86XVUpdateCompositeClip(portPriv);
783*4882a593Smuzhiyun 
784*4882a593Smuzhiyun     /* the clip can get smaller over time */
785*4882a593Smuzhiyun     RegionCopy(portPriv->clientClip, portPriv->pCompositeClip);
786*4882a593Smuzhiyun     RegionTranslate(portPriv->clientClip,
787*4882a593Smuzhiyun                     -portPriv->pDraw->x, -portPriv->pDraw->y);
788*4882a593Smuzhiyun 
789*4882a593Smuzhiyun     /* translate the video region to the screen */
790*4882a593Smuzhiyun     WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
791*4882a593Smuzhiyun     WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
792*4882a593Smuzhiyun     WinBox.x2 = WinBox.x1 + portPriv->drw_w;
793*4882a593Smuzhiyun     WinBox.y2 = WinBox.y1 + portPriv->drw_h;
794*4882a593Smuzhiyun 
795*4882a593Smuzhiyun     /* clip to the window composite clip */
796*4882a593Smuzhiyun     RegionInit(&WinRegion, &WinBox, 1);
797*4882a593Smuzhiyun     RegionNull(&ClipRegion);
798*4882a593Smuzhiyun     RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
799*4882a593Smuzhiyun 
800*4882a593Smuzhiyun     /* clip and translate to the viewport */
801*4882a593Smuzhiyun     if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
802*4882a593Smuzhiyun         RegionRec VPReg;
803*4882a593Smuzhiyun         BoxRec VPBox;
804*4882a593Smuzhiyun 
805*4882a593Smuzhiyun         VPBox.x1 = portPriv->pScrn->frameX0;
806*4882a593Smuzhiyun         VPBox.y1 = portPriv->pScrn->frameY0;
807*4882a593Smuzhiyun         VPBox.x2 = portPriv->pScrn->frameX1 + 1;
808*4882a593Smuzhiyun         VPBox.y2 = portPriv->pScrn->frameY1 + 1;
809*4882a593Smuzhiyun 
810*4882a593Smuzhiyun         RegionInit(&VPReg, &VPBox, 1);
811*4882a593Smuzhiyun         RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
812*4882a593Smuzhiyun         RegionUninit(&VPReg);
813*4882a593Smuzhiyun     }
814*4882a593Smuzhiyun 
815*4882a593Smuzhiyun     /* that's all if it's totally obscured */
816*4882a593Smuzhiyun     if (!RegionNotEmpty(&ClipRegion)) {
817*4882a593Smuzhiyun         clippedAway = TRUE;
818*4882a593Smuzhiyun         goto CLIP_VIDEO_BAILOUT;
819*4882a593Smuzhiyun     }
820*4882a593Smuzhiyun 
821*4882a593Smuzhiyun     ret = (*portPriv->AdaptorRec->ReputImage) (portPriv->pScrn,
822*4882a593Smuzhiyun                                                portPriv->vid_x, portPriv->vid_y,
823*4882a593Smuzhiyun                                                WinBox.x1, WinBox.y1,
824*4882a593Smuzhiyun                                                portPriv->vid_w, portPriv->vid_h,
825*4882a593Smuzhiyun                                                portPriv->drw_w, portPriv->drw_h,
826*4882a593Smuzhiyun                                                &ClipRegion,
827*4882a593Smuzhiyun                                                portPriv->DevPriv.ptr,
828*4882a593Smuzhiyun                                                portPriv->pDraw);
829*4882a593Smuzhiyun 
830*4882a593Smuzhiyun     portPriv->isOn = (ret == Success) ? XV_ON : XV_OFF;
831*4882a593Smuzhiyun 
832*4882a593Smuzhiyun  CLIP_VIDEO_BAILOUT:
833*4882a593Smuzhiyun 
834*4882a593Smuzhiyun     if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
835*4882a593Smuzhiyun         (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
836*4882a593Smuzhiyun                                             portPriv->DevPriv.ptr, FALSE);
837*4882a593Smuzhiyun         portPriv->isOn = XV_PENDING;
838*4882a593Smuzhiyun     }
839*4882a593Smuzhiyun 
840*4882a593Smuzhiyun     /* This clip was copied and only good for one shot */
841*4882a593Smuzhiyun     if (!portPriv->FreeCompositeClip)
842*4882a593Smuzhiyun         portPriv->pCompositeClip = NULL;
843*4882a593Smuzhiyun 
844*4882a593Smuzhiyun     RegionUninit(&WinRegion);
845*4882a593Smuzhiyun     RegionUninit(&ClipRegion);
846*4882a593Smuzhiyun 
847*4882a593Smuzhiyun     return ret;
848*4882a593Smuzhiyun }
849*4882a593Smuzhiyun 
850*4882a593Smuzhiyun static int
xf86XVReputAllVideo(WindowPtr pWin,void * data)851*4882a593Smuzhiyun xf86XVReputAllVideo(WindowPtr pWin, void *data)
852*4882a593Smuzhiyun {
853*4882a593Smuzhiyun     XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
854*4882a593Smuzhiyun 
855*4882a593Smuzhiyun     while (WinPriv) {
856*4882a593Smuzhiyun         if (WinPriv->PortRec->type == XvInputMask)
857*4882a593Smuzhiyun             xf86XVReputVideo(WinPriv->PortRec);
858*4882a593Smuzhiyun         else
859*4882a593Smuzhiyun             xf86XVRegetVideo(WinPriv->PortRec);
860*4882a593Smuzhiyun         WinPriv = WinPriv->next;
861*4882a593Smuzhiyun     }
862*4882a593Smuzhiyun 
863*4882a593Smuzhiyun     return WT_WALKCHILDREN;
864*4882a593Smuzhiyun }
865*4882a593Smuzhiyun 
866*4882a593Smuzhiyun static int
xf86XVEnlistPortInWindow(WindowPtr pWin,XvPortRecPrivatePtr portPriv)867*4882a593Smuzhiyun xf86XVEnlistPortInWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
868*4882a593Smuzhiyun {
869*4882a593Smuzhiyun     XF86XVWindowPtr winPriv, PrivRoot;
870*4882a593Smuzhiyun 
871*4882a593Smuzhiyun     winPriv = PrivRoot = GET_XF86XV_WINDOW(pWin);
872*4882a593Smuzhiyun 
873*4882a593Smuzhiyun     /* Enlist our port in the window private */
874*4882a593Smuzhiyun     while (winPriv) {
875*4882a593Smuzhiyun         if (winPriv->PortRec == portPriv)       /* we're already listed */
876*4882a593Smuzhiyun             break;
877*4882a593Smuzhiyun         winPriv = winPriv->next;
878*4882a593Smuzhiyun     }
879*4882a593Smuzhiyun 
880*4882a593Smuzhiyun     if (!winPriv) {
881*4882a593Smuzhiyun         winPriv = calloc(1, sizeof(XF86XVWindowRec));
882*4882a593Smuzhiyun         if (!winPriv)
883*4882a593Smuzhiyun             return BadAlloc;
884*4882a593Smuzhiyun         winPriv->PortRec = portPriv;
885*4882a593Smuzhiyun         winPriv->next = PrivRoot;
886*4882a593Smuzhiyun         dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, winPriv);
887*4882a593Smuzhiyun     }
888*4882a593Smuzhiyun 
889*4882a593Smuzhiyun     portPriv->pDraw = (DrawablePtr) pWin;
890*4882a593Smuzhiyun 
891*4882a593Smuzhiyun     return Success;
892*4882a593Smuzhiyun }
893*4882a593Smuzhiyun 
894*4882a593Smuzhiyun static void
xf86XVRemovePortFromWindow(WindowPtr pWin,XvPortRecPrivatePtr portPriv)895*4882a593Smuzhiyun xf86XVRemovePortFromWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
896*4882a593Smuzhiyun {
897*4882a593Smuzhiyun     XF86XVWindowPtr winPriv, prevPriv = NULL;
898*4882a593Smuzhiyun 
899*4882a593Smuzhiyun     winPriv = GET_XF86XV_WINDOW(pWin);
900*4882a593Smuzhiyun 
901*4882a593Smuzhiyun     while (winPriv) {
902*4882a593Smuzhiyun         if (winPriv->PortRec == portPriv) {
903*4882a593Smuzhiyun             if (prevPriv)
904*4882a593Smuzhiyun                 prevPriv->next = winPriv->next;
905*4882a593Smuzhiyun             else
906*4882a593Smuzhiyun                 dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey,
907*4882a593Smuzhiyun                               winPriv->next);
908*4882a593Smuzhiyun             free(winPriv);
909*4882a593Smuzhiyun             break;
910*4882a593Smuzhiyun         }
911*4882a593Smuzhiyun         prevPriv = winPriv;
912*4882a593Smuzhiyun         winPriv = winPriv->next;
913*4882a593Smuzhiyun     }
914*4882a593Smuzhiyun     portPriv->pDraw = NULL;
915*4882a593Smuzhiyun     if (portPriv->ckeyFilled) {
916*4882a593Smuzhiyun         RegionDestroy(portPriv->ckeyFilled);
917*4882a593Smuzhiyun         portPriv->ckeyFilled = NULL;
918*4882a593Smuzhiyun     }
919*4882a593Smuzhiyun     portPriv->clipChanged = FALSE;
920*4882a593Smuzhiyun }
921*4882a593Smuzhiyun 
922*4882a593Smuzhiyun static void
xf86XVReputOrStopPort(XvPortRecPrivatePtr pPriv,WindowPtr pWin,Bool visible)923*4882a593Smuzhiyun xf86XVReputOrStopPort(XvPortRecPrivatePtr pPriv, WindowPtr pWin, Bool visible)
924*4882a593Smuzhiyun {
925*4882a593Smuzhiyun     if (!visible) {
926*4882a593Smuzhiyun         if (pPriv->isOn == XV_ON) {
927*4882a593Smuzhiyun             (*pPriv->AdaptorRec->StopVideo) (pPriv->pScrn, pPriv->DevPriv.ptr,
928*4882a593Smuzhiyun                                              FALSE);
929*4882a593Smuzhiyun             pPriv->isOn = XV_PENDING;
930*4882a593Smuzhiyun         }
931*4882a593Smuzhiyun 
932*4882a593Smuzhiyun         if (!pPriv->type)       /* overlaid still/image */
933*4882a593Smuzhiyun             xf86XVRemovePortFromWindow(pWin, pPriv);
934*4882a593Smuzhiyun 
935*4882a593Smuzhiyun         return;
936*4882a593Smuzhiyun     }
937*4882a593Smuzhiyun 
938*4882a593Smuzhiyun     switch (pPriv->type) {
939*4882a593Smuzhiyun     case XvInputMask:
940*4882a593Smuzhiyun         xf86XVReputVideo(pPriv);
941*4882a593Smuzhiyun         break;
942*4882a593Smuzhiyun     case XvOutputMask:
943*4882a593Smuzhiyun         xf86XVRegetVideo(pPriv);
944*4882a593Smuzhiyun         break;
945*4882a593Smuzhiyun     default:                   /* overlaid still/image */
946*4882a593Smuzhiyun         if (pPriv->AdaptorRec->ReputImage)
947*4882a593Smuzhiyun             xf86XVReputImage(pPriv);
948*4882a593Smuzhiyun         break;
949*4882a593Smuzhiyun     }
950*4882a593Smuzhiyun }
951*4882a593Smuzhiyun 
952*4882a593Smuzhiyun static void
xf86XVReputOrStopAllPorts(ScrnInfoPtr pScrn,Bool onlyChanged)953*4882a593Smuzhiyun xf86XVReputOrStopAllPorts(ScrnInfoPtr pScrn, Bool onlyChanged)
954*4882a593Smuzhiyun {
955*4882a593Smuzhiyun     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
956*4882a593Smuzhiyun     XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
957*4882a593Smuzhiyun     XvAdaptorPtr pa;
958*4882a593Smuzhiyun     int c, i;
959*4882a593Smuzhiyun 
960*4882a593Smuzhiyun     for (c = pxvs->nAdaptors, pa = pxvs->pAdaptors; c > 0; c--, pa++) {
961*4882a593Smuzhiyun         XvPortPtr pPort = pa->pPorts;
962*4882a593Smuzhiyun 
963*4882a593Smuzhiyun         for (i = pa->nPorts; i > 0; i--, pPort++) {
964*4882a593Smuzhiyun             XvPortRecPrivatePtr pPriv =
965*4882a593Smuzhiyun                 (XvPortRecPrivatePtr) pPort->devPriv.ptr;
966*4882a593Smuzhiyun             WindowPtr pWin = (WindowPtr) pPriv->pDraw;
967*4882a593Smuzhiyun             Bool visible;
968*4882a593Smuzhiyun 
969*4882a593Smuzhiyun             if (pPriv->isOn == XV_OFF || !pWin)
970*4882a593Smuzhiyun                 continue;
971*4882a593Smuzhiyun 
972*4882a593Smuzhiyun             if (onlyChanged && !pPriv->clipChanged)
973*4882a593Smuzhiyun                 continue;
974*4882a593Smuzhiyun 
975*4882a593Smuzhiyun             visible = pWin->visibility == VisibilityUnobscured ||
976*4882a593Smuzhiyun                 pWin->visibility == VisibilityPartiallyObscured;
977*4882a593Smuzhiyun 
978*4882a593Smuzhiyun             /*
979*4882a593Smuzhiyun              * Stop and remove still/images if
980*4882a593Smuzhiyun              * ReputImage isn't supported.
981*4882a593Smuzhiyun              */
982*4882a593Smuzhiyun             if (!pPriv->type && !pPriv->AdaptorRec->ReputImage)
983*4882a593Smuzhiyun                 visible = FALSE;
984*4882a593Smuzhiyun 
985*4882a593Smuzhiyun             xf86XVReputOrStopPort(pPriv, pWin, visible);
986*4882a593Smuzhiyun 
987*4882a593Smuzhiyun             pPriv->clipChanged = FALSE;
988*4882a593Smuzhiyun         }
989*4882a593Smuzhiyun     }
990*4882a593Smuzhiyun }
991*4882a593Smuzhiyun 
992*4882a593Smuzhiyun /****  ScreenRec fields ****/
993*4882a593Smuzhiyun 
994*4882a593Smuzhiyun static Bool
xf86XVDestroyWindow(WindowPtr pWin)995*4882a593Smuzhiyun xf86XVDestroyWindow(WindowPtr pWin)
996*4882a593Smuzhiyun {
997*4882a593Smuzhiyun     ScreenPtr pScreen = pWin->drawable.pScreen;
998*4882a593Smuzhiyun     XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
999*4882a593Smuzhiyun     XF86XVWindowPtr tmp, WinPriv = GET_XF86XV_WINDOW(pWin);
1000*4882a593Smuzhiyun     int ret;
1001*4882a593Smuzhiyun 
1002*4882a593Smuzhiyun     while (WinPriv) {
1003*4882a593Smuzhiyun         XvPortRecPrivatePtr pPriv = WinPriv->PortRec;
1004*4882a593Smuzhiyun 
1005*4882a593Smuzhiyun         if (pPriv->isOn > XV_OFF) {
1006*4882a593Smuzhiyun             (*pPriv->AdaptorRec->StopVideo) (pPriv->pScrn, pPriv->DevPriv.ptr,
1007*4882a593Smuzhiyun                                              TRUE);
1008*4882a593Smuzhiyun             pPriv->isOn = XV_OFF;
1009*4882a593Smuzhiyun         }
1010*4882a593Smuzhiyun 
1011*4882a593Smuzhiyun         pPriv->pDraw = NULL;
1012*4882a593Smuzhiyun         tmp = WinPriv;
1013*4882a593Smuzhiyun         WinPriv = WinPriv->next;
1014*4882a593Smuzhiyun         free(tmp);
1015*4882a593Smuzhiyun     }
1016*4882a593Smuzhiyun 
1017*4882a593Smuzhiyun     dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, NULL);
1018*4882a593Smuzhiyun 
1019*4882a593Smuzhiyun     pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
1020*4882a593Smuzhiyun     ret = (*pScreen->DestroyWindow) (pWin);
1021*4882a593Smuzhiyun     pScreen->DestroyWindow = xf86XVDestroyWindow;
1022*4882a593Smuzhiyun 
1023*4882a593Smuzhiyun     return ret;
1024*4882a593Smuzhiyun }
1025*4882a593Smuzhiyun 
1026*4882a593Smuzhiyun static void
xf86XVPostValidateTree(WindowPtr pWin,WindowPtr pLayerWin,VTKind kind)1027*4882a593Smuzhiyun xf86XVPostValidateTree(WindowPtr pWin, WindowPtr pLayerWin, VTKind kind)
1028*4882a593Smuzhiyun {
1029*4882a593Smuzhiyun     ScreenPtr pScreen;
1030*4882a593Smuzhiyun     XF86XVScreenPtr ScreenPriv;
1031*4882a593Smuzhiyun     ScrnInfoPtr pScrn;
1032*4882a593Smuzhiyun 
1033*4882a593Smuzhiyun     if (pWin)
1034*4882a593Smuzhiyun         pScreen = pWin->drawable.pScreen;
1035*4882a593Smuzhiyun     else
1036*4882a593Smuzhiyun         pScreen = pLayerWin->drawable.pScreen;
1037*4882a593Smuzhiyun 
1038*4882a593Smuzhiyun     ScreenPriv = GET_XF86XV_SCREEN(pScreen);
1039*4882a593Smuzhiyun     pScrn = xf86ScreenToScrn(pScreen);
1040*4882a593Smuzhiyun 
1041*4882a593Smuzhiyun     xf86XVReputOrStopAllPorts(pScrn, TRUE);
1042*4882a593Smuzhiyun 
1043*4882a593Smuzhiyun     pScreen->PostValidateTree = ScreenPriv->PostValidateTree;
1044*4882a593Smuzhiyun     if (pScreen->PostValidateTree) {
1045*4882a593Smuzhiyun         (*pScreen->PostValidateTree) (pWin, pLayerWin, kind);
1046*4882a593Smuzhiyun     }
1047*4882a593Smuzhiyun     ScreenPriv->PostValidateTree = PostValidateTreeUndefined;
1048*4882a593Smuzhiyun }
1049*4882a593Smuzhiyun 
1050*4882a593Smuzhiyun static void
xf86XVWindowExposures(WindowPtr pWin,RegionPtr reg1)1051*4882a593Smuzhiyun xf86XVWindowExposures(WindowPtr pWin, RegionPtr reg1)
1052*4882a593Smuzhiyun {
1053*4882a593Smuzhiyun     ScreenPtr pScreen = pWin->drawable.pScreen;
1054*4882a593Smuzhiyun     XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
1055*4882a593Smuzhiyun     XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
1056*4882a593Smuzhiyun     XvPortRecPrivatePtr pPriv;
1057*4882a593Smuzhiyun     Bool AreasExposed;
1058*4882a593Smuzhiyun 
1059*4882a593Smuzhiyun     AreasExposed = (WinPriv && reg1 && RegionNotEmpty(reg1));
1060*4882a593Smuzhiyun 
1061*4882a593Smuzhiyun     pScreen->WindowExposures = ScreenPriv->WindowExposures;
1062*4882a593Smuzhiyun     (*pScreen->WindowExposures) (pWin, reg1);
1063*4882a593Smuzhiyun     pScreen->WindowExposures = xf86XVWindowExposures;
1064*4882a593Smuzhiyun 
1065*4882a593Smuzhiyun     /* filter out XClearWindow/Area */
1066*4882a593Smuzhiyun     if (!pWin->valdata)
1067*4882a593Smuzhiyun         return;
1068*4882a593Smuzhiyun 
1069*4882a593Smuzhiyun     while (WinPriv) {
1070*4882a593Smuzhiyun         Bool visible = TRUE;
1071*4882a593Smuzhiyun 
1072*4882a593Smuzhiyun         pPriv = WinPriv->PortRec;
1073*4882a593Smuzhiyun 
1074*4882a593Smuzhiyun         /*
1075*4882a593Smuzhiyun          * Stop and remove still/images if areas were exposed and
1076*4882a593Smuzhiyun          * ReputImage isn't supported.
1077*4882a593Smuzhiyun          */
1078*4882a593Smuzhiyun         if (!pPriv->type && !pPriv->AdaptorRec->ReputImage)
1079*4882a593Smuzhiyun             visible = !AreasExposed;
1080*4882a593Smuzhiyun 
1081*4882a593Smuzhiyun         /*
1082*4882a593Smuzhiyun          * Subtract exposed areas from overlaid image to match textured video
1083*4882a593Smuzhiyun          * behavior.
1084*4882a593Smuzhiyun          */
1085*4882a593Smuzhiyun         if (!pPriv->type && pPriv->clientClip)
1086*4882a593Smuzhiyun             RegionSubtract(pPriv->clientClip, pPriv->clientClip, reg1);
1087*4882a593Smuzhiyun 
1088*4882a593Smuzhiyun         if (visible && pPriv->ckeyFilled) {
1089*4882a593Smuzhiyun             RegionRec tmp;
1090*4882a593Smuzhiyun 
1091*4882a593Smuzhiyun             RegionNull(&tmp);
1092*4882a593Smuzhiyun             RegionCopy(&tmp, reg1);
1093*4882a593Smuzhiyun             RegionTranslate(&tmp, pWin->drawable.x, pWin->drawable.y);
1094*4882a593Smuzhiyun             RegionSubtract(pPriv->ckeyFilled, pPriv->ckeyFilled, &tmp);
1095*4882a593Smuzhiyun         }
1096*4882a593Smuzhiyun 
1097*4882a593Smuzhiyun         WinPriv = WinPriv->next;
1098*4882a593Smuzhiyun         xf86XVReputOrStopPort(pPriv, pWin, visible);
1099*4882a593Smuzhiyun 
1100*4882a593Smuzhiyun         pPriv->clipChanged = FALSE;
1101*4882a593Smuzhiyun     }
1102*4882a593Smuzhiyun }
1103*4882a593Smuzhiyun 
1104*4882a593Smuzhiyun static void
xf86XVClipNotify(WindowPtr pWin,int dx,int dy)1105*4882a593Smuzhiyun xf86XVClipNotify(WindowPtr pWin, int dx, int dy)
1106*4882a593Smuzhiyun {
1107*4882a593Smuzhiyun     ScreenPtr pScreen = pWin->drawable.pScreen;
1108*4882a593Smuzhiyun     XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
1109*4882a593Smuzhiyun     XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
1110*4882a593Smuzhiyun     XvPortRecPrivatePtr pPriv;
1111*4882a593Smuzhiyun 
1112*4882a593Smuzhiyun     while (WinPriv) {
1113*4882a593Smuzhiyun         pPriv = WinPriv->PortRec;
1114*4882a593Smuzhiyun 
1115*4882a593Smuzhiyun         if (pPriv->pCompositeClip && pPriv->FreeCompositeClip)
1116*4882a593Smuzhiyun             RegionDestroy(pPriv->pCompositeClip);
1117*4882a593Smuzhiyun 
1118*4882a593Smuzhiyun         pPriv->pCompositeClip = NULL;
1119*4882a593Smuzhiyun 
1120*4882a593Smuzhiyun         pPriv->clipChanged = TRUE;
1121*4882a593Smuzhiyun 
1122*4882a593Smuzhiyun         if (ScreenPriv->PostValidateTree == PostValidateTreeUndefined) {
1123*4882a593Smuzhiyun             ScreenPriv->PostValidateTree = pScreen->PostValidateTree;
1124*4882a593Smuzhiyun             pScreen->PostValidateTree = xf86XVPostValidateTree;
1125*4882a593Smuzhiyun         }
1126*4882a593Smuzhiyun 
1127*4882a593Smuzhiyun         WinPriv = WinPriv->next;
1128*4882a593Smuzhiyun     }
1129*4882a593Smuzhiyun 
1130*4882a593Smuzhiyun     if (ScreenPriv->ClipNotify) {
1131*4882a593Smuzhiyun         pScreen->ClipNotify = ScreenPriv->ClipNotify;
1132*4882a593Smuzhiyun         (*pScreen->ClipNotify) (pWin, dx, dy);
1133*4882a593Smuzhiyun         pScreen->ClipNotify = xf86XVClipNotify;
1134*4882a593Smuzhiyun     }
1135*4882a593Smuzhiyun }
1136*4882a593Smuzhiyun 
1137*4882a593Smuzhiyun /**** Required XvScreenRec fields ****/
1138*4882a593Smuzhiyun 
1139*4882a593Smuzhiyun static Bool
xf86XVCloseScreen(ScreenPtr pScreen)1140*4882a593Smuzhiyun xf86XVCloseScreen(ScreenPtr pScreen)
1141*4882a593Smuzhiyun {
1142*4882a593Smuzhiyun     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1143*4882a593Smuzhiyun     XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
1144*4882a593Smuzhiyun     XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
1145*4882a593Smuzhiyun     XvAdaptorPtr pa;
1146*4882a593Smuzhiyun     int c;
1147*4882a593Smuzhiyun 
1148*4882a593Smuzhiyun     if (!ScreenPriv)
1149*4882a593Smuzhiyun         return TRUE;
1150*4882a593Smuzhiyun 
1151*4882a593Smuzhiyun     pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
1152*4882a593Smuzhiyun     pScreen->WindowExposures = ScreenPriv->WindowExposures;
1153*4882a593Smuzhiyun     pScreen->ClipNotify = ScreenPriv->ClipNotify;
1154*4882a593Smuzhiyun     pScreen->CloseScreen = ScreenPriv->CloseScreen;
1155*4882a593Smuzhiyun 
1156*4882a593Smuzhiyun     pScrn->EnterVT = ScreenPriv->EnterVT;
1157*4882a593Smuzhiyun     pScrn->LeaveVT = ScreenPriv->LeaveVT;
1158*4882a593Smuzhiyun     pScrn->AdjustFrame = ScreenPriv->AdjustFrame;
1159*4882a593Smuzhiyun     pScrn->ModeSet = ScreenPriv->ModeSet;
1160*4882a593Smuzhiyun 
1161*4882a593Smuzhiyun     for (c = 0, pa = pxvs->pAdaptors; c < pxvs->nAdaptors; c++, pa++) {
1162*4882a593Smuzhiyun         xf86XVFreeAdaptor(pa);
1163*4882a593Smuzhiyun     }
1164*4882a593Smuzhiyun 
1165*4882a593Smuzhiyun     free(pxvs->pAdaptors);
1166*4882a593Smuzhiyun     free(ScreenPriv);
1167*4882a593Smuzhiyun 
1168*4882a593Smuzhiyun     return pScreen->CloseScreen(pScreen);
1169*4882a593Smuzhiyun }
1170*4882a593Smuzhiyun 
1171*4882a593Smuzhiyun /**** ScrnInfoRec fields ****/
1172*4882a593Smuzhiyun 
1173*4882a593Smuzhiyun static Bool
xf86XVEnterVT(ScrnInfoPtr pScrn)1174*4882a593Smuzhiyun xf86XVEnterVT(ScrnInfoPtr pScrn)
1175*4882a593Smuzhiyun {
1176*4882a593Smuzhiyun     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
1177*4882a593Smuzhiyun     XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
1178*4882a593Smuzhiyun     Bool ret;
1179*4882a593Smuzhiyun 
1180*4882a593Smuzhiyun     pScrn->EnterVT = ScreenPriv->EnterVT;
1181*4882a593Smuzhiyun     ret = (*ScreenPriv->EnterVT) (pScrn);
1182*4882a593Smuzhiyun     ScreenPriv->EnterVT = pScrn->EnterVT;
1183*4882a593Smuzhiyun     pScrn->EnterVT = xf86XVEnterVT;
1184*4882a593Smuzhiyun 
1185*4882a593Smuzhiyun     if (ret)
1186*4882a593Smuzhiyun         WalkTree(pScreen, xf86XVReputAllVideo, 0);
1187*4882a593Smuzhiyun 
1188*4882a593Smuzhiyun     return ret;
1189*4882a593Smuzhiyun }
1190*4882a593Smuzhiyun 
1191*4882a593Smuzhiyun static void
xf86XVLeaveVT(ScrnInfoPtr pScrn)1192*4882a593Smuzhiyun xf86XVLeaveVT(ScrnInfoPtr pScrn)
1193*4882a593Smuzhiyun {
1194*4882a593Smuzhiyun     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
1195*4882a593Smuzhiyun     XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
1196*4882a593Smuzhiyun     XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
1197*4882a593Smuzhiyun     XvAdaptorPtr pAdaptor;
1198*4882a593Smuzhiyun     XvPortPtr pPort;
1199*4882a593Smuzhiyun     XvPortRecPrivatePtr pPriv;
1200*4882a593Smuzhiyun     int i, j;
1201*4882a593Smuzhiyun 
1202*4882a593Smuzhiyun     for (i = 0; i < pxvs->nAdaptors; i++) {
1203*4882a593Smuzhiyun         pAdaptor = &pxvs->pAdaptors[i];
1204*4882a593Smuzhiyun         for (j = 0; j < pAdaptor->nPorts; j++) {
1205*4882a593Smuzhiyun             pPort = &pAdaptor->pPorts[j];
1206*4882a593Smuzhiyun             pPriv = (XvPortRecPrivatePtr) pPort->devPriv.ptr;
1207*4882a593Smuzhiyun             if (pPriv->isOn > XV_OFF) {
1208*4882a593Smuzhiyun 
1209*4882a593Smuzhiyun                 (*pPriv->AdaptorRec->StopVideo) (pPriv->pScrn,
1210*4882a593Smuzhiyun                                                  pPriv->DevPriv.ptr, TRUE);
1211*4882a593Smuzhiyun                 pPriv->isOn = XV_OFF;
1212*4882a593Smuzhiyun 
1213*4882a593Smuzhiyun                 if (pPriv->pCompositeClip && pPriv->FreeCompositeClip)
1214*4882a593Smuzhiyun                     RegionDestroy(pPriv->pCompositeClip);
1215*4882a593Smuzhiyun 
1216*4882a593Smuzhiyun                 pPriv->pCompositeClip = NULL;
1217*4882a593Smuzhiyun 
1218*4882a593Smuzhiyun                 if (!pPriv->type && pPriv->pDraw) {     /* still */
1219*4882a593Smuzhiyun                     xf86XVRemovePortFromWindow((WindowPtr) pPriv->pDraw, pPriv);
1220*4882a593Smuzhiyun                 }
1221*4882a593Smuzhiyun             }
1222*4882a593Smuzhiyun         }
1223*4882a593Smuzhiyun     }
1224*4882a593Smuzhiyun 
1225*4882a593Smuzhiyun     pScrn->LeaveVT = ScreenPriv->LeaveVT;
1226*4882a593Smuzhiyun     (*ScreenPriv->LeaveVT) (pScrn);
1227*4882a593Smuzhiyun     ScreenPriv->LeaveVT = pScrn->LeaveVT;
1228*4882a593Smuzhiyun     pScrn->LeaveVT = xf86XVLeaveVT;
1229*4882a593Smuzhiyun }
1230*4882a593Smuzhiyun 
1231*4882a593Smuzhiyun static void
xf86XVAdjustFrame(ScrnInfoPtr pScrn,int x,int y)1232*4882a593Smuzhiyun xf86XVAdjustFrame(ScrnInfoPtr pScrn, int x, int y)
1233*4882a593Smuzhiyun {
1234*4882a593Smuzhiyun     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
1235*4882a593Smuzhiyun     XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
1236*4882a593Smuzhiyun 
1237*4882a593Smuzhiyun     if (ScreenPriv->AdjustFrame) {
1238*4882a593Smuzhiyun         pScrn->AdjustFrame = ScreenPriv->AdjustFrame;
1239*4882a593Smuzhiyun         (*pScrn->AdjustFrame) (pScrn, x, y);
1240*4882a593Smuzhiyun         pScrn->AdjustFrame = xf86XVAdjustFrame;
1241*4882a593Smuzhiyun     }
1242*4882a593Smuzhiyun 
1243*4882a593Smuzhiyun     xf86XVReputOrStopAllPorts(pScrn, FALSE);
1244*4882a593Smuzhiyun }
1245*4882a593Smuzhiyun 
1246*4882a593Smuzhiyun static void
xf86XVModeSet(ScrnInfoPtr pScrn)1247*4882a593Smuzhiyun xf86XVModeSet(ScrnInfoPtr pScrn)
1248*4882a593Smuzhiyun {
1249*4882a593Smuzhiyun     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
1250*4882a593Smuzhiyun     XF86XVScreenPtr ScreenPriv;
1251*4882a593Smuzhiyun 
1252*4882a593Smuzhiyun     /* Can be called before pScrn->pScreen is set */
1253*4882a593Smuzhiyun     if (!pScreen)
1254*4882a593Smuzhiyun         return;
1255*4882a593Smuzhiyun 
1256*4882a593Smuzhiyun     ScreenPriv = GET_XF86XV_SCREEN(pScreen);
1257*4882a593Smuzhiyun 
1258*4882a593Smuzhiyun     if (ScreenPriv->ModeSet) {
1259*4882a593Smuzhiyun         pScrn->ModeSet = ScreenPriv->ModeSet;
1260*4882a593Smuzhiyun         (*pScrn->ModeSet) (pScrn);
1261*4882a593Smuzhiyun         pScrn->ModeSet = xf86XVModeSet;
1262*4882a593Smuzhiyun     }
1263*4882a593Smuzhiyun 
1264*4882a593Smuzhiyun     xf86XVReputOrStopAllPorts(pScrn, FALSE);
1265*4882a593Smuzhiyun }
1266*4882a593Smuzhiyun 
1267*4882a593Smuzhiyun /**** XvAdaptorRec fields ****/
1268*4882a593Smuzhiyun 
1269*4882a593Smuzhiyun static int
xf86XVPutVideo(DrawablePtr pDraw,XvPortPtr pPort,GCPtr pGC,INT16 vid_x,INT16 vid_y,CARD16 vid_w,CARD16 vid_h,INT16 drw_x,INT16 drw_y,CARD16 drw_w,CARD16 drw_h)1270*4882a593Smuzhiyun xf86XVPutVideo(DrawablePtr pDraw,
1271*4882a593Smuzhiyun                XvPortPtr pPort,
1272*4882a593Smuzhiyun                GCPtr pGC,
1273*4882a593Smuzhiyun                INT16 vid_x, INT16 vid_y,
1274*4882a593Smuzhiyun                CARD16 vid_w, CARD16 vid_h,
1275*4882a593Smuzhiyun                INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
1276*4882a593Smuzhiyun {
1277*4882a593Smuzhiyun     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1278*4882a593Smuzhiyun     int result;
1279*4882a593Smuzhiyun 
1280*4882a593Smuzhiyun     /* No dumping video to pixmaps... For now anyhow */
1281*4882a593Smuzhiyun     if (pDraw->type != DRAWABLE_WINDOW) {
1282*4882a593Smuzhiyun         pPort->pDraw = (DrawablePtr) NULL;
1283*4882a593Smuzhiyun         return BadAlloc;
1284*4882a593Smuzhiyun     }
1285*4882a593Smuzhiyun 
1286*4882a593Smuzhiyun     /* If we are changing windows, unregister our port in the old window */
1287*4882a593Smuzhiyun     if (portPriv->pDraw && (portPriv->pDraw != pDraw))
1288*4882a593Smuzhiyun         xf86XVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
1289*4882a593Smuzhiyun 
1290*4882a593Smuzhiyun     /* Register our port with the new window */
1291*4882a593Smuzhiyun     result = xf86XVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
1292*4882a593Smuzhiyun     if (result != Success)
1293*4882a593Smuzhiyun         return result;
1294*4882a593Smuzhiyun 
1295*4882a593Smuzhiyun     portPriv->type = XvInputMask;
1296*4882a593Smuzhiyun 
1297*4882a593Smuzhiyun     /* save a copy of these parameters */
1298*4882a593Smuzhiyun     portPriv->vid_x = vid_x;
1299*4882a593Smuzhiyun     portPriv->vid_y = vid_y;
1300*4882a593Smuzhiyun     portPriv->vid_w = vid_w;
1301*4882a593Smuzhiyun     portPriv->vid_h = vid_h;
1302*4882a593Smuzhiyun     portPriv->drw_x = drw_x;
1303*4882a593Smuzhiyun     portPriv->drw_y = drw_y;
1304*4882a593Smuzhiyun     portPriv->drw_w = drw_w;
1305*4882a593Smuzhiyun     portPriv->drw_h = drw_h;
1306*4882a593Smuzhiyun 
1307*4882a593Smuzhiyun     /* make sure we have the most recent copy of the clientClip */
1308*4882a593Smuzhiyun     xf86XVCopyClip(portPriv, pGC);
1309*4882a593Smuzhiyun 
1310*4882a593Smuzhiyun     /* To indicate to the DI layer that we were successful */
1311*4882a593Smuzhiyun     pPort->pDraw = pDraw;
1312*4882a593Smuzhiyun 
1313*4882a593Smuzhiyun     if (!portPriv->pScrn->vtSema)
1314*4882a593Smuzhiyun         return Success;         /* Success ? */
1315*4882a593Smuzhiyun 
1316*4882a593Smuzhiyun     return (xf86XVReputVideo(portPriv));
1317*4882a593Smuzhiyun }
1318*4882a593Smuzhiyun 
1319*4882a593Smuzhiyun static int
xf86XVPutStill(DrawablePtr pDraw,XvPortPtr pPort,GCPtr pGC,INT16 vid_x,INT16 vid_y,CARD16 vid_w,CARD16 vid_h,INT16 drw_x,INT16 drw_y,CARD16 drw_w,CARD16 drw_h)1320*4882a593Smuzhiyun xf86XVPutStill(DrawablePtr pDraw,
1321*4882a593Smuzhiyun                XvPortPtr pPort,
1322*4882a593Smuzhiyun                GCPtr pGC,
1323*4882a593Smuzhiyun                INT16 vid_x, INT16 vid_y,
1324*4882a593Smuzhiyun                CARD16 vid_w, CARD16 vid_h,
1325*4882a593Smuzhiyun                INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
1326*4882a593Smuzhiyun {
1327*4882a593Smuzhiyun     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1328*4882a593Smuzhiyun     RegionRec WinRegion;
1329*4882a593Smuzhiyun     RegionRec ClipRegion;
1330*4882a593Smuzhiyun     BoxRec WinBox;
1331*4882a593Smuzhiyun     int ret = Success;
1332*4882a593Smuzhiyun     Bool clippedAway = FALSE;
1333*4882a593Smuzhiyun 
1334*4882a593Smuzhiyun     if (pDraw->type != DRAWABLE_WINDOW)
1335*4882a593Smuzhiyun         return BadAlloc;
1336*4882a593Smuzhiyun 
1337*4882a593Smuzhiyun     if (!portPriv->pScrn->vtSema)
1338*4882a593Smuzhiyun         return Success;         /* Success ? */
1339*4882a593Smuzhiyun 
1340*4882a593Smuzhiyun     WinBox.x1 = pDraw->x + drw_x;
1341*4882a593Smuzhiyun     WinBox.y1 = pDraw->y + drw_y;
1342*4882a593Smuzhiyun     WinBox.x2 = WinBox.x1 + drw_w;
1343*4882a593Smuzhiyun     WinBox.y2 = WinBox.y1 + drw_h;
1344*4882a593Smuzhiyun 
1345*4882a593Smuzhiyun     xf86XVCopyCompositeClip(portPriv, pGC, pDraw);
1346*4882a593Smuzhiyun 
1347*4882a593Smuzhiyun     RegionInit(&WinRegion, &WinBox, 1);
1348*4882a593Smuzhiyun     RegionNull(&ClipRegion);
1349*4882a593Smuzhiyun     RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
1350*4882a593Smuzhiyun 
1351*4882a593Smuzhiyun     if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
1352*4882a593Smuzhiyun         RegionRec VPReg;
1353*4882a593Smuzhiyun         BoxRec VPBox;
1354*4882a593Smuzhiyun 
1355*4882a593Smuzhiyun         VPBox.x1 = portPriv->pScrn->frameX0;
1356*4882a593Smuzhiyun         VPBox.y1 = portPriv->pScrn->frameY0;
1357*4882a593Smuzhiyun         VPBox.x2 = portPriv->pScrn->frameX1 + 1;
1358*4882a593Smuzhiyun         VPBox.y2 = portPriv->pScrn->frameY1 + 1;
1359*4882a593Smuzhiyun 
1360*4882a593Smuzhiyun         RegionInit(&VPReg, &VPBox, 1);
1361*4882a593Smuzhiyun         RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
1362*4882a593Smuzhiyun         RegionUninit(&VPReg);
1363*4882a593Smuzhiyun     }
1364*4882a593Smuzhiyun 
1365*4882a593Smuzhiyun     if (portPriv->pDraw) {
1366*4882a593Smuzhiyun         xf86XVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
1367*4882a593Smuzhiyun     }
1368*4882a593Smuzhiyun 
1369*4882a593Smuzhiyun     if (!RegionNotEmpty(&ClipRegion)) {
1370*4882a593Smuzhiyun         clippedAway = TRUE;
1371*4882a593Smuzhiyun         goto PUT_STILL_BAILOUT;
1372*4882a593Smuzhiyun     }
1373*4882a593Smuzhiyun 
1374*4882a593Smuzhiyun     ret = (*portPriv->AdaptorRec->PutStill) (portPriv->pScrn,
1375*4882a593Smuzhiyun                                              vid_x, vid_y, WinBox.x1, WinBox.y1,
1376*4882a593Smuzhiyun                                              vid_w, vid_h, drw_w, drw_h,
1377*4882a593Smuzhiyun                                              &ClipRegion, portPriv->DevPriv.ptr,
1378*4882a593Smuzhiyun                                              pDraw);
1379*4882a593Smuzhiyun 
1380*4882a593Smuzhiyun     if ((ret == Success) &&
1381*4882a593Smuzhiyun         (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_STILLS)) {
1382*4882a593Smuzhiyun 
1383*4882a593Smuzhiyun         xf86XVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
1384*4882a593Smuzhiyun         portPriv->isOn = XV_ON;
1385*4882a593Smuzhiyun         portPriv->vid_x = vid_x;
1386*4882a593Smuzhiyun         portPriv->vid_y = vid_y;
1387*4882a593Smuzhiyun         portPriv->vid_w = vid_w;
1388*4882a593Smuzhiyun         portPriv->vid_h = vid_h;
1389*4882a593Smuzhiyun         portPriv->drw_x = drw_x;
1390*4882a593Smuzhiyun         portPriv->drw_y = drw_y;
1391*4882a593Smuzhiyun         portPriv->drw_w = drw_w;
1392*4882a593Smuzhiyun         portPriv->drw_h = drw_h;
1393*4882a593Smuzhiyun         portPriv->type = 0;     /* no mask means it's transient and should
1394*4882a593Smuzhiyun                                    not be reput once it's removed */
1395*4882a593Smuzhiyun         pPort->pDraw = pDraw;   /* make sure we can get stop requests */
1396*4882a593Smuzhiyun     }
1397*4882a593Smuzhiyun 
1398*4882a593Smuzhiyun  PUT_STILL_BAILOUT:
1399*4882a593Smuzhiyun 
1400*4882a593Smuzhiyun     if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
1401*4882a593Smuzhiyun         (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
1402*4882a593Smuzhiyun                                             portPriv->DevPriv.ptr, FALSE);
1403*4882a593Smuzhiyun         portPriv->isOn = XV_PENDING;
1404*4882a593Smuzhiyun     }
1405*4882a593Smuzhiyun 
1406*4882a593Smuzhiyun     /* This clip was copied and only good for one shot */
1407*4882a593Smuzhiyun     if (!portPriv->FreeCompositeClip)
1408*4882a593Smuzhiyun         portPriv->pCompositeClip = NULL;
1409*4882a593Smuzhiyun 
1410*4882a593Smuzhiyun     RegionUninit(&WinRegion);
1411*4882a593Smuzhiyun     RegionUninit(&ClipRegion);
1412*4882a593Smuzhiyun 
1413*4882a593Smuzhiyun     return ret;
1414*4882a593Smuzhiyun }
1415*4882a593Smuzhiyun 
1416*4882a593Smuzhiyun static int
xf86XVGetVideo(DrawablePtr pDraw,XvPortPtr pPort,GCPtr pGC,INT16 vid_x,INT16 vid_y,CARD16 vid_w,CARD16 vid_h,INT16 drw_x,INT16 drw_y,CARD16 drw_w,CARD16 drw_h)1417*4882a593Smuzhiyun xf86XVGetVideo(DrawablePtr pDraw,
1418*4882a593Smuzhiyun                XvPortPtr pPort,
1419*4882a593Smuzhiyun                GCPtr pGC,
1420*4882a593Smuzhiyun                INT16 vid_x, INT16 vid_y,
1421*4882a593Smuzhiyun                CARD16 vid_w, CARD16 vid_h,
1422*4882a593Smuzhiyun                INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
1423*4882a593Smuzhiyun {
1424*4882a593Smuzhiyun     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1425*4882a593Smuzhiyun     int result;
1426*4882a593Smuzhiyun 
1427*4882a593Smuzhiyun     /* No pixmaps... For now anyhow */
1428*4882a593Smuzhiyun     if (pDraw->type != DRAWABLE_WINDOW) {
1429*4882a593Smuzhiyun         pPort->pDraw = (DrawablePtr) NULL;
1430*4882a593Smuzhiyun         return BadAlloc;
1431*4882a593Smuzhiyun     }
1432*4882a593Smuzhiyun 
1433*4882a593Smuzhiyun     /* If we are changing windows, unregister our port in the old window */
1434*4882a593Smuzhiyun     if (portPriv->pDraw && (portPriv->pDraw != pDraw))
1435*4882a593Smuzhiyun         xf86XVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
1436*4882a593Smuzhiyun 
1437*4882a593Smuzhiyun     /* Register our port with the new window */
1438*4882a593Smuzhiyun     result = xf86XVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
1439*4882a593Smuzhiyun     if (result != Success)
1440*4882a593Smuzhiyun         return result;
1441*4882a593Smuzhiyun 
1442*4882a593Smuzhiyun     portPriv->type = XvOutputMask;
1443*4882a593Smuzhiyun 
1444*4882a593Smuzhiyun     /* save a copy of these parameters */
1445*4882a593Smuzhiyun     portPriv->vid_x = vid_x;
1446*4882a593Smuzhiyun     portPriv->vid_y = vid_y;
1447*4882a593Smuzhiyun     portPriv->vid_w = vid_w;
1448*4882a593Smuzhiyun     portPriv->vid_h = vid_h;
1449*4882a593Smuzhiyun     portPriv->drw_x = drw_x;
1450*4882a593Smuzhiyun     portPriv->drw_y = drw_y;
1451*4882a593Smuzhiyun     portPriv->drw_w = drw_w;
1452*4882a593Smuzhiyun     portPriv->drw_h = drw_h;
1453*4882a593Smuzhiyun 
1454*4882a593Smuzhiyun     /* make sure we have the most recent copy of the clientClip */
1455*4882a593Smuzhiyun     xf86XVCopyClip(portPriv, pGC);
1456*4882a593Smuzhiyun 
1457*4882a593Smuzhiyun     /* To indicate to the DI layer that we were successful */
1458*4882a593Smuzhiyun     pPort->pDraw = pDraw;
1459*4882a593Smuzhiyun 
1460*4882a593Smuzhiyun     if (!portPriv->pScrn->vtSema)
1461*4882a593Smuzhiyun         return Success;         /* Success ? */
1462*4882a593Smuzhiyun 
1463*4882a593Smuzhiyun     return (xf86XVRegetVideo(portPriv));
1464*4882a593Smuzhiyun }
1465*4882a593Smuzhiyun 
1466*4882a593Smuzhiyun static int
xf86XVGetStill(DrawablePtr pDraw,XvPortPtr pPort,GCPtr pGC,INT16 vid_x,INT16 vid_y,CARD16 vid_w,CARD16 vid_h,INT16 drw_x,INT16 drw_y,CARD16 drw_w,CARD16 drw_h)1467*4882a593Smuzhiyun xf86XVGetStill(DrawablePtr pDraw,
1468*4882a593Smuzhiyun                XvPortPtr pPort,
1469*4882a593Smuzhiyun                GCPtr pGC,
1470*4882a593Smuzhiyun                INT16 vid_x, INT16 vid_y,
1471*4882a593Smuzhiyun                CARD16 vid_w, CARD16 vid_h,
1472*4882a593Smuzhiyun                INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
1473*4882a593Smuzhiyun {
1474*4882a593Smuzhiyun     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1475*4882a593Smuzhiyun     RegionRec WinRegion;
1476*4882a593Smuzhiyun     RegionRec ClipRegion;
1477*4882a593Smuzhiyun     BoxRec WinBox;
1478*4882a593Smuzhiyun     int ret = Success;
1479*4882a593Smuzhiyun     Bool clippedAway = FALSE;
1480*4882a593Smuzhiyun 
1481*4882a593Smuzhiyun     if (pDraw->type != DRAWABLE_WINDOW)
1482*4882a593Smuzhiyun         return BadAlloc;
1483*4882a593Smuzhiyun 
1484*4882a593Smuzhiyun     if (!portPriv->pScrn->vtSema)
1485*4882a593Smuzhiyun         return Success;         /* Success ? */
1486*4882a593Smuzhiyun 
1487*4882a593Smuzhiyun     WinBox.x1 = pDraw->x + drw_x;
1488*4882a593Smuzhiyun     WinBox.y1 = pDraw->y + drw_y;
1489*4882a593Smuzhiyun     WinBox.x2 = WinBox.x1 + drw_w;
1490*4882a593Smuzhiyun     WinBox.y2 = WinBox.y1 + drw_h;
1491*4882a593Smuzhiyun 
1492*4882a593Smuzhiyun     RegionInit(&WinRegion, &WinBox, 1);
1493*4882a593Smuzhiyun     RegionNull(&ClipRegion);
1494*4882a593Smuzhiyun     RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
1495*4882a593Smuzhiyun 
1496*4882a593Smuzhiyun     if (portPriv->pDraw) {
1497*4882a593Smuzhiyun         xf86XVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
1498*4882a593Smuzhiyun     }
1499*4882a593Smuzhiyun 
1500*4882a593Smuzhiyun     if (!RegionNotEmpty(&ClipRegion)) {
1501*4882a593Smuzhiyun         clippedAway = TRUE;
1502*4882a593Smuzhiyun         goto GET_STILL_BAILOUT;
1503*4882a593Smuzhiyun     }
1504*4882a593Smuzhiyun 
1505*4882a593Smuzhiyun     ret = (*portPriv->AdaptorRec->GetStill) (portPriv->pScrn,
1506*4882a593Smuzhiyun                                              vid_x, vid_y, WinBox.x1, WinBox.y1,
1507*4882a593Smuzhiyun                                              vid_w, vid_h, drw_w, drw_h,
1508*4882a593Smuzhiyun                                              &ClipRegion, portPriv->DevPriv.ptr,
1509*4882a593Smuzhiyun                                              pDraw);
1510*4882a593Smuzhiyun 
1511*4882a593Smuzhiyun  GET_STILL_BAILOUT:
1512*4882a593Smuzhiyun 
1513*4882a593Smuzhiyun     if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
1514*4882a593Smuzhiyun         (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
1515*4882a593Smuzhiyun                                             portPriv->DevPriv.ptr, FALSE);
1516*4882a593Smuzhiyun         portPriv->isOn = XV_PENDING;
1517*4882a593Smuzhiyun     }
1518*4882a593Smuzhiyun 
1519*4882a593Smuzhiyun     RegionUninit(&WinRegion);
1520*4882a593Smuzhiyun     RegionUninit(&ClipRegion);
1521*4882a593Smuzhiyun 
1522*4882a593Smuzhiyun     return ret;
1523*4882a593Smuzhiyun }
1524*4882a593Smuzhiyun 
1525*4882a593Smuzhiyun static int
xf86XVStopVideo(XvPortPtr pPort,DrawablePtr pDraw)1526*4882a593Smuzhiyun xf86XVStopVideo(XvPortPtr pPort, DrawablePtr pDraw)
1527*4882a593Smuzhiyun {
1528*4882a593Smuzhiyun     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1529*4882a593Smuzhiyun 
1530*4882a593Smuzhiyun     if (pDraw->type != DRAWABLE_WINDOW)
1531*4882a593Smuzhiyun         return BadAlloc;
1532*4882a593Smuzhiyun 
1533*4882a593Smuzhiyun     xf86XVRemovePortFromWindow((WindowPtr) pDraw, portPriv);
1534*4882a593Smuzhiyun 
1535*4882a593Smuzhiyun     if (!portPriv->pScrn->vtSema)
1536*4882a593Smuzhiyun         return Success;         /* Success ? */
1537*4882a593Smuzhiyun 
1538*4882a593Smuzhiyun     /* Must free resources. */
1539*4882a593Smuzhiyun 
1540*4882a593Smuzhiyun     if (portPriv->isOn > XV_OFF) {
1541*4882a593Smuzhiyun         (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
1542*4882a593Smuzhiyun                                             portPriv->DevPriv.ptr, TRUE);
1543*4882a593Smuzhiyun         portPriv->isOn = XV_OFF;
1544*4882a593Smuzhiyun     }
1545*4882a593Smuzhiyun 
1546*4882a593Smuzhiyun     return Success;
1547*4882a593Smuzhiyun }
1548*4882a593Smuzhiyun 
1549*4882a593Smuzhiyun static int
xf86XVSetPortAttribute(XvPortPtr pPort,Atom attribute,INT32 value)1550*4882a593Smuzhiyun xf86XVSetPortAttribute(XvPortPtr pPort, Atom attribute, INT32 value)
1551*4882a593Smuzhiyun {
1552*4882a593Smuzhiyun     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1553*4882a593Smuzhiyun 
1554*4882a593Smuzhiyun     return ((*portPriv->AdaptorRec->SetPortAttribute) (portPriv->pScrn,
1555*4882a593Smuzhiyun                                                        attribute, value,
1556*4882a593Smuzhiyun                                                        portPriv->DevPriv.ptr));
1557*4882a593Smuzhiyun }
1558*4882a593Smuzhiyun 
1559*4882a593Smuzhiyun static int
xf86XVGetPortAttribute(XvPortPtr pPort,Atom attribute,INT32 * p_value)1560*4882a593Smuzhiyun xf86XVGetPortAttribute(XvPortPtr pPort, Atom attribute, INT32 *p_value)
1561*4882a593Smuzhiyun {
1562*4882a593Smuzhiyun     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1563*4882a593Smuzhiyun 
1564*4882a593Smuzhiyun     return ((*portPriv->AdaptorRec->GetPortAttribute) (portPriv->pScrn,
1565*4882a593Smuzhiyun                                                        attribute, p_value,
1566*4882a593Smuzhiyun                                                        portPriv->DevPriv.ptr));
1567*4882a593Smuzhiyun }
1568*4882a593Smuzhiyun 
1569*4882a593Smuzhiyun static int
xf86XVQueryBestSize(XvPortPtr pPort,CARD8 motion,CARD16 vid_w,CARD16 vid_h,CARD16 drw_w,CARD16 drw_h,unsigned int * p_w,unsigned int * p_h)1570*4882a593Smuzhiyun xf86XVQueryBestSize(XvPortPtr pPort,
1571*4882a593Smuzhiyun                     CARD8 motion,
1572*4882a593Smuzhiyun                     CARD16 vid_w, CARD16 vid_h,
1573*4882a593Smuzhiyun                     CARD16 drw_w, CARD16 drw_h,
1574*4882a593Smuzhiyun                     unsigned int *p_w, unsigned int *p_h)
1575*4882a593Smuzhiyun {
1576*4882a593Smuzhiyun     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1577*4882a593Smuzhiyun 
1578*4882a593Smuzhiyun     (*portPriv->AdaptorRec->QueryBestSize) (portPriv->pScrn,
1579*4882a593Smuzhiyun                                             (Bool) motion, vid_w, vid_h, drw_w,
1580*4882a593Smuzhiyun                                             drw_h, p_w, p_h,
1581*4882a593Smuzhiyun                                             portPriv->DevPriv.ptr);
1582*4882a593Smuzhiyun 
1583*4882a593Smuzhiyun     return Success;
1584*4882a593Smuzhiyun }
1585*4882a593Smuzhiyun 
1586*4882a593Smuzhiyun static int
xf86XVPutImage(DrawablePtr pDraw,XvPortPtr pPort,GCPtr pGC,INT16 src_x,INT16 src_y,CARD16 src_w,CARD16 src_h,INT16 drw_x,INT16 drw_y,CARD16 drw_w,CARD16 drw_h,XvImagePtr format,unsigned char * data,Bool sync,CARD16 width,CARD16 height)1587*4882a593Smuzhiyun xf86XVPutImage(DrawablePtr pDraw,
1588*4882a593Smuzhiyun                XvPortPtr pPort,
1589*4882a593Smuzhiyun                GCPtr pGC,
1590*4882a593Smuzhiyun                INT16 src_x, INT16 src_y,
1591*4882a593Smuzhiyun                CARD16 src_w, CARD16 src_h,
1592*4882a593Smuzhiyun                INT16 drw_x, INT16 drw_y,
1593*4882a593Smuzhiyun                CARD16 drw_w, CARD16 drw_h,
1594*4882a593Smuzhiyun                XvImagePtr format,
1595*4882a593Smuzhiyun                unsigned char *data, Bool sync, CARD16 width, CARD16 height)
1596*4882a593Smuzhiyun {
1597*4882a593Smuzhiyun     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1598*4882a593Smuzhiyun     RegionRec WinRegion;
1599*4882a593Smuzhiyun     RegionRec ClipRegion;
1600*4882a593Smuzhiyun     BoxRec WinBox;
1601*4882a593Smuzhiyun     int ret = Success;
1602*4882a593Smuzhiyun     Bool clippedAway = FALSE;
1603*4882a593Smuzhiyun 
1604*4882a593Smuzhiyun     if (pDraw->type != DRAWABLE_WINDOW)
1605*4882a593Smuzhiyun         return BadAlloc;
1606*4882a593Smuzhiyun 
1607*4882a593Smuzhiyun     if (!portPriv->pScrn->vtSema)
1608*4882a593Smuzhiyun         return Success;         /* Success ? */
1609*4882a593Smuzhiyun 
1610*4882a593Smuzhiyun     xf86XVCopyCompositeClip(portPriv, pGC, pDraw);
1611*4882a593Smuzhiyun 
1612*4882a593Smuzhiyun     WinBox.x1 = pDraw->x + drw_x;
1613*4882a593Smuzhiyun     WinBox.y1 = pDraw->y + drw_y;
1614*4882a593Smuzhiyun     WinBox.x2 = WinBox.x1 + drw_w;
1615*4882a593Smuzhiyun     WinBox.y2 = WinBox.y1 + drw_h;
1616*4882a593Smuzhiyun 
1617*4882a593Smuzhiyun     RegionInit(&WinRegion, &WinBox, 1);
1618*4882a593Smuzhiyun     RegionNull(&ClipRegion);
1619*4882a593Smuzhiyun     RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
1620*4882a593Smuzhiyun 
1621*4882a593Smuzhiyun     if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
1622*4882a593Smuzhiyun         RegionRec VPReg;
1623*4882a593Smuzhiyun         BoxRec VPBox;
1624*4882a593Smuzhiyun 
1625*4882a593Smuzhiyun         VPBox.x1 = portPriv->pScrn->frameX0;
1626*4882a593Smuzhiyun         VPBox.y1 = portPriv->pScrn->frameY0;
1627*4882a593Smuzhiyun         VPBox.x2 = portPriv->pScrn->frameX1 + 1;
1628*4882a593Smuzhiyun         VPBox.y2 = portPriv->pScrn->frameY1 + 1;
1629*4882a593Smuzhiyun 
1630*4882a593Smuzhiyun         RegionInit(&VPReg, &VPBox, 1);
1631*4882a593Smuzhiyun         RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
1632*4882a593Smuzhiyun         RegionUninit(&VPReg);
1633*4882a593Smuzhiyun     }
1634*4882a593Smuzhiyun 
1635*4882a593Smuzhiyun     /* If we are changing windows, unregister our port in the old window */
1636*4882a593Smuzhiyun     if (portPriv->pDraw && (portPriv->pDraw != pDraw))
1637*4882a593Smuzhiyun         xf86XVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
1638*4882a593Smuzhiyun 
1639*4882a593Smuzhiyun     /* Register our port with the new window */
1640*4882a593Smuzhiyun     ret = xf86XVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
1641*4882a593Smuzhiyun     if (ret != Success)
1642*4882a593Smuzhiyun         goto PUT_IMAGE_BAILOUT;
1643*4882a593Smuzhiyun 
1644*4882a593Smuzhiyun     if (!RegionNotEmpty(&ClipRegion)) {
1645*4882a593Smuzhiyun         clippedAway = TRUE;
1646*4882a593Smuzhiyun         goto PUT_IMAGE_BAILOUT;
1647*4882a593Smuzhiyun     }
1648*4882a593Smuzhiyun 
1649*4882a593Smuzhiyun     ret = (*portPriv->AdaptorRec->PutImage) (portPriv->pScrn,
1650*4882a593Smuzhiyun                                              src_x, src_y, WinBox.x1, WinBox.y1,
1651*4882a593Smuzhiyun                                              src_w, src_h, drw_w, drw_h,
1652*4882a593Smuzhiyun                                              format->id, data, width, height,
1653*4882a593Smuzhiyun                                              sync, &ClipRegion,
1654*4882a593Smuzhiyun                                              portPriv->DevPriv.ptr, pDraw);
1655*4882a593Smuzhiyun 
1656*4882a593Smuzhiyun     if ((ret == Success) &&
1657*4882a593Smuzhiyun         (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_IMAGES)) {
1658*4882a593Smuzhiyun 
1659*4882a593Smuzhiyun         portPriv->isOn = XV_ON;
1660*4882a593Smuzhiyun         portPriv->vid_x = src_x;
1661*4882a593Smuzhiyun         portPriv->vid_y = src_y;
1662*4882a593Smuzhiyun         portPriv->vid_w = src_w;
1663*4882a593Smuzhiyun         portPriv->vid_h = src_h;
1664*4882a593Smuzhiyun         portPriv->drw_x = drw_x;
1665*4882a593Smuzhiyun         portPriv->drw_y = drw_y;
1666*4882a593Smuzhiyun         portPriv->drw_w = drw_w;
1667*4882a593Smuzhiyun         portPriv->drw_h = drw_h;
1668*4882a593Smuzhiyun         portPriv->type = 0;     /* no mask means it's transient and should
1669*4882a593Smuzhiyun                                    not be reput once it's removed */
1670*4882a593Smuzhiyun         pPort->pDraw = pDraw;   /* make sure we can get stop requests */
1671*4882a593Smuzhiyun     }
1672*4882a593Smuzhiyun 
1673*4882a593Smuzhiyun  PUT_IMAGE_BAILOUT:
1674*4882a593Smuzhiyun 
1675*4882a593Smuzhiyun     if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
1676*4882a593Smuzhiyun         (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
1677*4882a593Smuzhiyun                                             portPriv->DevPriv.ptr, FALSE);
1678*4882a593Smuzhiyun         portPriv->isOn = XV_PENDING;
1679*4882a593Smuzhiyun     }
1680*4882a593Smuzhiyun 
1681*4882a593Smuzhiyun     /* This clip was copied and only good for one shot */
1682*4882a593Smuzhiyun     if (!portPriv->FreeCompositeClip)
1683*4882a593Smuzhiyun         portPriv->pCompositeClip = NULL;
1684*4882a593Smuzhiyun 
1685*4882a593Smuzhiyun     RegionUninit(&WinRegion);
1686*4882a593Smuzhiyun     RegionUninit(&ClipRegion);
1687*4882a593Smuzhiyun 
1688*4882a593Smuzhiyun     return ret;
1689*4882a593Smuzhiyun }
1690*4882a593Smuzhiyun 
1691*4882a593Smuzhiyun static int
xf86XVQueryImageAttributes(XvPortPtr pPort,XvImagePtr format,CARD16 * width,CARD16 * height,int * pitches,int * offsets)1692*4882a593Smuzhiyun xf86XVQueryImageAttributes(XvPortPtr pPort,
1693*4882a593Smuzhiyun                            XvImagePtr format,
1694*4882a593Smuzhiyun                            CARD16 *width,
1695*4882a593Smuzhiyun                            CARD16 *height, int *pitches, int *offsets)
1696*4882a593Smuzhiyun {
1697*4882a593Smuzhiyun     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1698*4882a593Smuzhiyun 
1699*4882a593Smuzhiyun     return (*portPriv->AdaptorRec->QueryImageAttributes) (portPriv->pScrn,
1700*4882a593Smuzhiyun                                                           format->id, width,
1701*4882a593Smuzhiyun                                                           height, pitches,
1702*4882a593Smuzhiyun                                                           offsets);
1703*4882a593Smuzhiyun }
1704*4882a593Smuzhiyun 
1705*4882a593Smuzhiyun void
xf86XVFillKeyHelperDrawable(DrawablePtr pDraw,CARD32 key,RegionPtr fillboxes)1706*4882a593Smuzhiyun xf86XVFillKeyHelperDrawable(DrawablePtr pDraw, CARD32 key, RegionPtr fillboxes)
1707*4882a593Smuzhiyun {
1708*4882a593Smuzhiyun     ScreenPtr pScreen = pDraw->pScreen;
1709*4882a593Smuzhiyun 
1710*4882a593Smuzhiyun     if (!xf86ScreenToScrn(pScreen)->vtSema)
1711*4882a593Smuzhiyun         return;
1712*4882a593Smuzhiyun 
1713*4882a593Smuzhiyun     XvFillColorKey(pDraw, key, fillboxes);
1714*4882a593Smuzhiyun }
1715*4882a593Smuzhiyun 
1716*4882a593Smuzhiyun void
xf86XVFillKeyHelper(ScreenPtr pScreen,CARD32 key,RegionPtr fillboxes)1717*4882a593Smuzhiyun xf86XVFillKeyHelper(ScreenPtr pScreen, CARD32 key, RegionPtr fillboxes)
1718*4882a593Smuzhiyun {
1719*4882a593Smuzhiyun     xf86XVFillKeyHelperDrawable(&pScreen->root->drawable, key, fillboxes);
1720*4882a593Smuzhiyun }
1721*4882a593Smuzhiyun 
1722*4882a593Smuzhiyun void
xf86XVFillKeyHelperPort(DrawablePtr pDraw,void * data,CARD32 key,RegionPtr clipboxes,Bool fillEverything)1723*4882a593Smuzhiyun xf86XVFillKeyHelperPort(DrawablePtr pDraw, void *data, CARD32 key,
1724*4882a593Smuzhiyun                         RegionPtr clipboxes, Bool fillEverything)
1725*4882a593Smuzhiyun {
1726*4882a593Smuzhiyun     WindowPtr pWin = (WindowPtr) pDraw;
1727*4882a593Smuzhiyun     XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
1728*4882a593Smuzhiyun     XvPortRecPrivatePtr portPriv = NULL;
1729*4882a593Smuzhiyun     RegionRec reg;
1730*4882a593Smuzhiyun     RegionPtr fillboxes;
1731*4882a593Smuzhiyun 
1732*4882a593Smuzhiyun     while (WinPriv) {
1733*4882a593Smuzhiyun         XvPortRecPrivatePtr pPriv = WinPriv->PortRec;
1734*4882a593Smuzhiyun 
1735*4882a593Smuzhiyun         if (data == pPriv->DevPriv.ptr) {
1736*4882a593Smuzhiyun             portPriv = pPriv;
1737*4882a593Smuzhiyun             break;
1738*4882a593Smuzhiyun         }
1739*4882a593Smuzhiyun 
1740*4882a593Smuzhiyun         WinPriv = WinPriv->next;
1741*4882a593Smuzhiyun     }
1742*4882a593Smuzhiyun 
1743*4882a593Smuzhiyun     if (!portPriv)
1744*4882a593Smuzhiyun         return;
1745*4882a593Smuzhiyun 
1746*4882a593Smuzhiyun     if (!portPriv->ckeyFilled)
1747*4882a593Smuzhiyun         portPriv->ckeyFilled = RegionCreate(NULL, 0);
1748*4882a593Smuzhiyun 
1749*4882a593Smuzhiyun     if (!fillEverything) {
1750*4882a593Smuzhiyun         RegionNull(&reg);
1751*4882a593Smuzhiyun         fillboxes = &reg;
1752*4882a593Smuzhiyun         RegionSubtract(fillboxes, clipboxes, portPriv->ckeyFilled);
1753*4882a593Smuzhiyun 
1754*4882a593Smuzhiyun         if (!RegionNotEmpty(fillboxes))
1755*4882a593Smuzhiyun             goto out;
1756*4882a593Smuzhiyun     }
1757*4882a593Smuzhiyun     else
1758*4882a593Smuzhiyun         fillboxes = clipboxes;
1759*4882a593Smuzhiyun 
1760*4882a593Smuzhiyun     RegionCopy(portPriv->ckeyFilled, clipboxes);
1761*4882a593Smuzhiyun 
1762*4882a593Smuzhiyun     xf86XVFillKeyHelperDrawable(pDraw, key, fillboxes);
1763*4882a593Smuzhiyun  out:
1764*4882a593Smuzhiyun     if (!fillEverything)
1765*4882a593Smuzhiyun         RegionUninit(&reg);
1766*4882a593Smuzhiyun }
1767*4882a593Smuzhiyun 
1768*4882a593Smuzhiyun /* xf86XVClipVideoHelper -
1769*4882a593Smuzhiyun 
1770*4882a593Smuzhiyun    Takes the dst box in standard X BoxRec form (top and left
1771*4882a593Smuzhiyun    edges inclusive, bottom and right exclusive).  The new dst
1772*4882a593Smuzhiyun    box is returned.  The source boundaries are given (x1, y1
1773*4882a593Smuzhiyun    inclusive, x2, y2 exclusive) and returned are the new source
1774*4882a593Smuzhiyun    boundaries in 16.16 fixed point.
1775*4882a593Smuzhiyun */
1776*4882a593Smuzhiyun 
1777*4882a593Smuzhiyun Bool
xf86XVClipVideoHelper(BoxPtr dst,INT32 * xa,INT32 * xb,INT32 * ya,INT32 * yb,RegionPtr reg,INT32 width,INT32 height)1778*4882a593Smuzhiyun xf86XVClipVideoHelper(BoxPtr dst,
1779*4882a593Smuzhiyun                       INT32 *xa,
1780*4882a593Smuzhiyun                       INT32 *xb,
1781*4882a593Smuzhiyun                       INT32 *ya,
1782*4882a593Smuzhiyun                       INT32 *yb, RegionPtr reg, INT32 width, INT32 height)
1783*4882a593Smuzhiyun {
1784*4882a593Smuzhiyun     double xsw, xdw, ysw, ydw;
1785*4882a593Smuzhiyun     INT32 delta;
1786*4882a593Smuzhiyun     BoxPtr extents = RegionExtents(reg);
1787*4882a593Smuzhiyun     int diff;
1788*4882a593Smuzhiyun 
1789*4882a593Smuzhiyun     xsw = (*xb - *xa) << 16;
1790*4882a593Smuzhiyun     xdw = dst->x2 - dst->x1;
1791*4882a593Smuzhiyun     ysw = (*yb - *ya) << 16;
1792*4882a593Smuzhiyun     ydw = dst->y2 - dst->y1;
1793*4882a593Smuzhiyun 
1794*4882a593Smuzhiyun     *xa <<= 16;
1795*4882a593Smuzhiyun     *xb <<= 16;
1796*4882a593Smuzhiyun     *ya <<= 16;
1797*4882a593Smuzhiyun     *yb <<= 16;
1798*4882a593Smuzhiyun 
1799*4882a593Smuzhiyun     diff = extents->x1 - dst->x1;
1800*4882a593Smuzhiyun     if (diff > 0) {
1801*4882a593Smuzhiyun         dst->x1 = extents->x1;
1802*4882a593Smuzhiyun         *xa += (diff * xsw) / xdw;
1803*4882a593Smuzhiyun     }
1804*4882a593Smuzhiyun     diff = dst->x2 - extents->x2;
1805*4882a593Smuzhiyun     if (diff > 0) {
1806*4882a593Smuzhiyun         dst->x2 = extents->x2;
1807*4882a593Smuzhiyun         *xb -= (diff * xsw) / xdw;
1808*4882a593Smuzhiyun     }
1809*4882a593Smuzhiyun     diff = extents->y1 - dst->y1;
1810*4882a593Smuzhiyun     if (diff > 0) {
1811*4882a593Smuzhiyun         dst->y1 = extents->y1;
1812*4882a593Smuzhiyun         *ya += (diff * ysw) / ydw;
1813*4882a593Smuzhiyun     }
1814*4882a593Smuzhiyun     diff = dst->y2 - extents->y2;
1815*4882a593Smuzhiyun     if (diff > 0) {
1816*4882a593Smuzhiyun         dst->y2 = extents->y2;
1817*4882a593Smuzhiyun         *yb -= (diff * ysw) / ydw;
1818*4882a593Smuzhiyun     }
1819*4882a593Smuzhiyun 
1820*4882a593Smuzhiyun     if (*xa < 0) {
1821*4882a593Smuzhiyun         diff = (((-*xa) * xdw) + xsw - 1) / xsw;
1822*4882a593Smuzhiyun         dst->x1 += diff;
1823*4882a593Smuzhiyun         *xa += (diff * xsw) / xdw;
1824*4882a593Smuzhiyun     }
1825*4882a593Smuzhiyun     delta = *xb - (width << 16);
1826*4882a593Smuzhiyun     if (delta > 0) {
1827*4882a593Smuzhiyun         diff = ((delta * xdw) + xsw - 1) / xsw;
1828*4882a593Smuzhiyun         dst->x2 -= diff;
1829*4882a593Smuzhiyun         *xb -= (diff * xsw) / xdw;
1830*4882a593Smuzhiyun     }
1831*4882a593Smuzhiyun     if (*xa >= *xb)
1832*4882a593Smuzhiyun         return FALSE;
1833*4882a593Smuzhiyun 
1834*4882a593Smuzhiyun     if (*ya < 0) {
1835*4882a593Smuzhiyun         diff = (((-*ya) * ydw) + ysw - 1) / ysw;
1836*4882a593Smuzhiyun         dst->y1 += diff;
1837*4882a593Smuzhiyun         *ya += (diff * ysw) / ydw;
1838*4882a593Smuzhiyun     }
1839*4882a593Smuzhiyun     delta = *yb - (height << 16);
1840*4882a593Smuzhiyun     if (delta > 0) {
1841*4882a593Smuzhiyun         diff = ((delta * ydw) + ysw - 1) / ysw;
1842*4882a593Smuzhiyun         dst->y2 -= diff;
1843*4882a593Smuzhiyun         *yb -= (diff * ysw) / ydw;
1844*4882a593Smuzhiyun     }
1845*4882a593Smuzhiyun     if (*ya >= *yb)
1846*4882a593Smuzhiyun         return FALSE;
1847*4882a593Smuzhiyun 
1848*4882a593Smuzhiyun     if ((dst->x1 > extents->x1) || (dst->x2 < extents->x2) ||
1849*4882a593Smuzhiyun         (dst->y1 > extents->y1) || (dst->y2 < extents->y2)) {
1850*4882a593Smuzhiyun         RegionRec clipReg;
1851*4882a593Smuzhiyun 
1852*4882a593Smuzhiyun         RegionInit(&clipReg, dst, 1);
1853*4882a593Smuzhiyun         RegionIntersect(reg, reg, &clipReg);
1854*4882a593Smuzhiyun         RegionUninit(&clipReg);
1855*4882a593Smuzhiyun     }
1856*4882a593Smuzhiyun     return TRUE;
1857*4882a593Smuzhiyun }
1858*4882a593Smuzhiyun 
1859*4882a593Smuzhiyun void
xf86XVCopyYUV12ToPacked(const void * srcy,const void * srcv,const void * srcu,void * dst,int srcPitchy,int srcPitchuv,int dstPitch,int h,int w)1860*4882a593Smuzhiyun xf86XVCopyYUV12ToPacked(const void *srcy,
1861*4882a593Smuzhiyun                         const void *srcv,
1862*4882a593Smuzhiyun                         const void *srcu,
1863*4882a593Smuzhiyun                         void *dst,
1864*4882a593Smuzhiyun                         int srcPitchy,
1865*4882a593Smuzhiyun                         int srcPitchuv, int dstPitch, int h, int w)
1866*4882a593Smuzhiyun {
1867*4882a593Smuzhiyun     CARD32 *Dst;
1868*4882a593Smuzhiyun     const CARD8 *Y, *U, *V;
1869*4882a593Smuzhiyun     int i, j;
1870*4882a593Smuzhiyun 
1871*4882a593Smuzhiyun     w >>= 1;
1872*4882a593Smuzhiyun 
1873*4882a593Smuzhiyun     for (j = 0; j < h; j++) {
1874*4882a593Smuzhiyun         Dst = dst;
1875*4882a593Smuzhiyun         Y = srcy;
1876*4882a593Smuzhiyun         V = srcv;
1877*4882a593Smuzhiyun         U = srcu;
1878*4882a593Smuzhiyun         i = w;
1879*4882a593Smuzhiyun         while (i >= 4) {
1880*4882a593Smuzhiyun #if X_BYTE_ORDER == X_LITTLE_ENDIAN
1881*4882a593Smuzhiyun             Dst[0] = Y[0] | (Y[1] << 16) | (U[0] << 8) | (V[0] << 24);
1882*4882a593Smuzhiyun             Dst[1] = Y[2] | (Y[3] << 16) | (U[1] << 8) | (V[1] << 24);
1883*4882a593Smuzhiyun             Dst[2] = Y[4] | (Y[5] << 16) | (U[2] << 8) | (V[2] << 24);
1884*4882a593Smuzhiyun             Dst[3] = Y[6] | (Y[7] << 16) | (U[3] << 8) | (V[3] << 24);
1885*4882a593Smuzhiyun #else
1886*4882a593Smuzhiyun             /* This assumes a little-endian framebuffer */
1887*4882a593Smuzhiyun             Dst[0] = (Y[0] << 24) | (Y[1] << 8) | (U[0] << 16) | V[0];
1888*4882a593Smuzhiyun             Dst[1] = (Y[2] << 24) | (Y[3] << 8) | (U[1] << 16) | V[1];
1889*4882a593Smuzhiyun             Dst[2] = (Y[4] << 24) | (Y[5] << 8) | (U[2] << 16) | V[2];
1890*4882a593Smuzhiyun             Dst[3] = (Y[6] << 24) | (Y[7] << 8) | (U[3] << 16) | V[3];
1891*4882a593Smuzhiyun #endif
1892*4882a593Smuzhiyun             Dst += 4;
1893*4882a593Smuzhiyun             Y += 8;
1894*4882a593Smuzhiyun             V += 4;
1895*4882a593Smuzhiyun             U += 4;
1896*4882a593Smuzhiyun             i -= 4;
1897*4882a593Smuzhiyun         }
1898*4882a593Smuzhiyun 
1899*4882a593Smuzhiyun         while (i--) {
1900*4882a593Smuzhiyun #if X_BYTE_ORDER == X_LITTLE_ENDIAN
1901*4882a593Smuzhiyun             Dst[0] = Y[0] | (Y[1] << 16) | (U[0] << 8) | (V[0] << 24);
1902*4882a593Smuzhiyun #else
1903*4882a593Smuzhiyun             /* This assumes a little-endian framebuffer */
1904*4882a593Smuzhiyun             Dst[0] = (Y[0] << 24) | (Y[1] << 8) | (U[0] << 16) | V[0];
1905*4882a593Smuzhiyun #endif
1906*4882a593Smuzhiyun             Dst++;
1907*4882a593Smuzhiyun             Y += 2;
1908*4882a593Smuzhiyun             V++;
1909*4882a593Smuzhiyun             U++;
1910*4882a593Smuzhiyun         }
1911*4882a593Smuzhiyun 
1912*4882a593Smuzhiyun         dst = (CARD8 *) dst + dstPitch;
1913*4882a593Smuzhiyun         srcy = (const CARD8 *) srcy + srcPitchy;
1914*4882a593Smuzhiyun         if (j & 1) {
1915*4882a593Smuzhiyun             srcu = (const CARD8 *) srcu + srcPitchuv;
1916*4882a593Smuzhiyun             srcv = (const CARD8 *) srcv + srcPitchuv;
1917*4882a593Smuzhiyun         }
1918*4882a593Smuzhiyun     }
1919*4882a593Smuzhiyun }
1920*4882a593Smuzhiyun 
1921*4882a593Smuzhiyun void
xf86XVCopyPacked(const void * src,void * dst,int srcPitch,int dstPitch,int h,int w)1922*4882a593Smuzhiyun xf86XVCopyPacked(const void *src,
1923*4882a593Smuzhiyun                  void *dst, int srcPitch, int dstPitch, int h, int w)
1924*4882a593Smuzhiyun {
1925*4882a593Smuzhiyun     const CARD32 *Src;
1926*4882a593Smuzhiyun     CARD32 *Dst;
1927*4882a593Smuzhiyun     int i;
1928*4882a593Smuzhiyun 
1929*4882a593Smuzhiyun     w >>= 1;
1930*4882a593Smuzhiyun     while (--h >= 0) {
1931*4882a593Smuzhiyun         do {
1932*4882a593Smuzhiyun             Dst = dst;
1933*4882a593Smuzhiyun             Src = src;
1934*4882a593Smuzhiyun             i = w;
1935*4882a593Smuzhiyun             while (i >= 4) {
1936*4882a593Smuzhiyun                 Dst[0] = Src[0];
1937*4882a593Smuzhiyun                 Dst[1] = Src[1];
1938*4882a593Smuzhiyun                 Dst[2] = Src[2];
1939*4882a593Smuzhiyun                 Dst[3] = Src[3];
1940*4882a593Smuzhiyun                 Dst += 4;
1941*4882a593Smuzhiyun                 Src += 4;
1942*4882a593Smuzhiyun                 i -= 4;
1943*4882a593Smuzhiyun             }
1944*4882a593Smuzhiyun             if (!i)
1945*4882a593Smuzhiyun                 break;
1946*4882a593Smuzhiyun             Dst[0] = Src[0];
1947*4882a593Smuzhiyun             if (i == 1)
1948*4882a593Smuzhiyun                 break;
1949*4882a593Smuzhiyun             Dst[1] = Src[1];
1950*4882a593Smuzhiyun             if (i == 2)
1951*4882a593Smuzhiyun                 break;
1952*4882a593Smuzhiyun             Dst[2] = Src[2];
1953*4882a593Smuzhiyun         } while (0);
1954*4882a593Smuzhiyun 
1955*4882a593Smuzhiyun         src = (const CARD8 *) src + srcPitch;
1956*4882a593Smuzhiyun         dst = (CARD8 *) dst + dstPitch;
1957*4882a593Smuzhiyun     }
1958*4882a593Smuzhiyun }
1959