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