1706f2543Smrg/*
2706f2543Smrg
3706f2543Smrg   XFree86 Xv DDX written by Mark Vojkovich (markv@valinux.com)
4706f2543Smrg   Adapted for KDrive by Pontus Lidman <pontus.lidman@nokia.com>
5706f2543Smrg
6706f2543Smrg   Copyright (C) 2000, 2001 - Nokia Home Communications
7706f2543Smrg   Copyright (C) 1998, 1999 - The XFree86 Project Inc.
8706f2543Smrg
9706f2543SmrgAll rights reserved.
10706f2543Smrg
11706f2543SmrgPermission is hereby granted, free of charge, to any person obtaining
12706f2543Smrga copy of this software and associated documentation files (the
13706f2543Smrg"Software"), to deal in the Software without restriction, including
14706f2543Smrgwithout limitation the rights to use, copy, modify, merge, publish,
15706f2543Smrgdistribute, and/or sell copies of the Software, and to permit persons
16706f2543Smrgto whom the Software is furnished to do so, provided that the above
17706f2543Smrgcopyright notice(s) and this permission notice appear in all copies of
18706f2543Smrgthe Software and that both the above copyright notice(s) and this
19706f2543Smrgpermission notice appear in supporting documentation.
20706f2543Smrg
21706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22706f2543SmrgEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23706f2543SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
24706f2543SmrgOF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
25706f2543SmrgHOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
26706f2543SmrgSPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
27706f2543SmrgRESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
28706f2543SmrgCONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
29706f2543SmrgCONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
30706f2543Smrg
31706f2543SmrgExcept as contained in this notice, the name of a copyright holder
32706f2543Smrgshall not be used in advertising or otherwise to promote the sale, use
33706f2543Smrgor other dealings in this Software without prior written authorization
34706f2543Smrgof the copyright holder.
35706f2543Smrg
36706f2543Smrg*/
37706f2543Smrg
38706f2543Smrg#ifdef HAVE_CONFIG_H
39706f2543Smrg#include <kdrive-config.h>
40706f2543Smrg#endif
41706f2543Smrg#include "kdrive.h"
42706f2543Smrg
43706f2543Smrg#include "scrnintstr.h"
44706f2543Smrg#include "regionstr.h"
45706f2543Smrg#include "windowstr.h"
46706f2543Smrg#include "pixmapstr.h"
47706f2543Smrg#include "mivalidate.h"
48706f2543Smrg#include "validate.h"
49706f2543Smrg#include "resource.h"
50706f2543Smrg#include "gcstruct.h"
51706f2543Smrg#include "dixstruct.h"
52706f2543Smrg
53706f2543Smrg#include <X11/extensions/Xv.h>
54706f2543Smrg#include <X11/extensions/Xvproto.h>
55706f2543Smrg
56706f2543Smrg#include "kxv.h"
57706f2543Smrg#include "fourcc.h"
58706f2543Smrg
59706f2543Smrg
60706f2543Smrg/* XvScreenRec fields */
61706f2543Smrg
62706f2543Smrgstatic Bool KdXVCloseScreen(int, ScreenPtr);
63706f2543Smrgstatic int KdXVQueryAdaptors(ScreenPtr, XvAdaptorPtr *, int *);
64706f2543Smrg
65706f2543Smrg/* XvAdaptorRec fields */
66706f2543Smrg
67706f2543Smrgstatic int KdXVAllocatePort(unsigned long, XvPortPtr, XvPortPtr*);
68706f2543Smrgstatic int KdXVFreePort(XvPortPtr);
69706f2543Smrgstatic int KdXVPutVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr,
70706f2543Smrg   				INT16, INT16, CARD16, CARD16,
71706f2543Smrg				INT16, INT16, CARD16, CARD16);
72706f2543Smrgstatic int KdXVPutStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr,
73706f2543Smrg   				INT16, INT16, CARD16, CARD16,
74706f2543Smrg				INT16, INT16, CARD16, CARD16);
75706f2543Smrgstatic int KdXVGetVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr,
76706f2543Smrg   				INT16, INT16, CARD16, CARD16,
77706f2543Smrg				INT16, INT16, CARD16, CARD16);
78706f2543Smrgstatic int KdXVGetStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr,
79706f2543Smrg   				INT16, INT16, CARD16, CARD16,
80706f2543Smrg				INT16, INT16, CARD16, CARD16);
81706f2543Smrgstatic int KdXVStopVideo(ClientPtr, XvPortPtr, DrawablePtr);
82706f2543Smrgstatic int KdXVSetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32);
83706f2543Smrgstatic int KdXVGetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32 *);
84706f2543Smrgstatic int KdXVQueryBestSize(ClientPtr, XvPortPtr, CARD8,
85706f2543Smrg   				CARD16, CARD16,CARD16, CARD16,
86706f2543Smrg				unsigned int*, unsigned int*);
87706f2543Smrgstatic int KdXVPutImage(ClientPtr, DrawablePtr, XvPortPtr, GCPtr,
88706f2543Smrg   				INT16, INT16, CARD16, CARD16,
89706f2543Smrg				INT16, INT16, CARD16, CARD16,
90706f2543Smrg				XvImagePtr, unsigned char*, Bool,
91706f2543Smrg				CARD16, CARD16);
92706f2543Smrgstatic int KdXVQueryImageAttributes(ClientPtr, XvPortPtr, XvImagePtr,
93706f2543Smrg				CARD16*, CARD16*, int*, int*);
94706f2543Smrg
95706f2543Smrg
96706f2543Smrg/* ScreenRec fields */
97706f2543Smrg
98706f2543Smrgstatic Bool KdXVCreateWindow(WindowPtr pWin);
99706f2543Smrgstatic Bool KdXVDestroyWindow(WindowPtr pWin);
100706f2543Smrgstatic void KdXVWindowExposures(WindowPtr pWin, RegionPtr r1, RegionPtr r2);
101706f2543Smrgstatic void KdXVClipNotify(WindowPtr pWin, int dx, int dy);
102706f2543Smrg
103706f2543Smrg/* misc */
104706f2543Smrgstatic Bool KdXVInitAdaptors(ScreenPtr, KdVideoAdaptorPtr*, int);
105706f2543Smrg
106706f2543Smrgstatic DevPrivateKeyRec KdXVWindowKeyRec;
107706f2543Smrg#define KdXVWindowKey (&KdXVWindowKeyRec)
108706f2543Smrgstatic DevPrivateKey KdXvScreenKey;
109706f2543Smrgstatic unsigned long KdXVGeneration = 0;
110706f2543Smrgstatic unsigned long PortResource = 0;
111706f2543Smrg
112706f2543SmrgDevPrivateKey (*XvGetScreenKeyProc)(void) = XvGetScreenKey;
113706f2543Smrgunsigned long (*XvGetRTPortProc)(void) = XvGetRTPort;
114706f2543Smrgint (*XvScreenInitProc)(ScreenPtr) = XvScreenInit;
115706f2543Smrg
116706f2543Smrg#define GET_XV_SCREEN(pScreen) ((XvScreenPtr) \
117706f2543Smrg    dixLookupPrivate(&(pScreen)->devPrivates, KdXvScreenKey))
118706f2543Smrg
119706f2543Smrg#define GET_KDXV_SCREEN(pScreen) \
120706f2543Smrg  	((KdXVScreenPtr)(GET_XV_SCREEN(pScreen)->devPriv.ptr))
121706f2543Smrg
122706f2543Smrg#define GET_KDXV_WINDOW(pWin) ((KdXVWindowPtr) \
123706f2543Smrg    dixLookupPrivate(&(pWin)->devPrivates, KdXVWindowKey))
124706f2543Smrg
125706f2543Smrgstatic KdXVInitGenericAdaptorPtr *GenDrivers = NULL;
126706f2543Smrgstatic int NumGenDrivers = 0;
127706f2543Smrg
128706f2543Smrgint
129706f2543SmrgKdXVRegisterGenericAdaptorDriver(
130706f2543Smrg    KdXVInitGenericAdaptorPtr InitFunc
131706f2543Smrg){
132706f2543Smrg  KdXVInitGenericAdaptorPtr *newdrivers;
133706f2543Smrg
134706f2543Smrg/*   fprintf(stderr,"KdXVRegisterGenericAdaptorDriver\n"); */
135706f2543Smrg
136706f2543Smrg  newdrivers = realloc(GenDrivers, sizeof(KdXVInitGenericAdaptorPtr) *
137706f2543Smrg			(1 + NumGenDrivers));
138706f2543Smrg  if (!newdrivers)
139706f2543Smrg    return 0;
140706f2543Smrg  GenDrivers = newdrivers;
141706f2543Smrg
142706f2543Smrg  GenDrivers[NumGenDrivers++] = InitFunc;
143706f2543Smrg
144706f2543Smrg  return 1;
145706f2543Smrg}
146706f2543Smrg
147706f2543Smrgint
148706f2543SmrgKdXVListGenericAdaptors(
149706f2543Smrg    KdScreenInfo *          screen,
150706f2543Smrg    KdVideoAdaptorPtr **adaptors
151706f2543Smrg){
152706f2543Smrg    int i,j,n,num;
153706f2543Smrg    KdVideoAdaptorPtr *DrivAdap,*new;
154706f2543Smrg
155706f2543Smrg    num = 0;
156706f2543Smrg    *adaptors = NULL;
157706f2543Smrg    for (i = 0; i < NumGenDrivers; i++) {
158706f2543Smrg	n = GenDrivers[i](screen,&DrivAdap);
159706f2543Smrg	if (0 == n)
160706f2543Smrg	    continue;
161706f2543Smrg	new = realloc(*adaptors, sizeof(KdVideoAdaptorPtr) * (num+n));
162706f2543Smrg	if (NULL == new)
163706f2543Smrg	    continue;
164706f2543Smrg	*adaptors = new;
165706f2543Smrg	for (j = 0; j < n; j++, num++)
166706f2543Smrg	    (*adaptors)[num] = DrivAdap[j];
167706f2543Smrg    }
168706f2543Smrg    return num;
169706f2543Smrg}
170706f2543Smrg
171706f2543SmrgKdVideoAdaptorPtr
172706f2543SmrgKdXVAllocateVideoAdaptorRec(KdScreenInfo * screen)
173706f2543Smrg{
174706f2543Smrg    return calloc(1, sizeof(KdVideoAdaptorRec));
175706f2543Smrg}
176706f2543Smrg
177706f2543Smrgvoid
178706f2543SmrgKdXVFreeVideoAdaptorRec(KdVideoAdaptorPtr ptr)
179706f2543Smrg{
180706f2543Smrg    free(ptr);
181706f2543Smrg}
182706f2543Smrg
183706f2543Smrg
184706f2543SmrgBool
185706f2543SmrgKdXVScreenInit(
186706f2543Smrg   ScreenPtr pScreen,
187706f2543Smrg   KdVideoAdaptorPtr *adaptors,
188706f2543Smrg   int num
189706f2543Smrg){
190706f2543Smrg  KdXVScreenPtr ScreenPriv;
191706f2543Smrg  XvScreenPtr pxvs;
192706f2543Smrg
193706f2543Smrg/*   fprintf(stderr,"KdXVScreenInit initializing %d adaptors\n",num); */
194706f2543Smrg
195706f2543Smrg  if (KdXVGeneration != serverGeneration)
196706f2543Smrg      KdXVGeneration = serverGeneration;
197706f2543Smrg
198706f2543Smrg  if(!XvGetScreenKeyProc || !XvGetRTPortProc || !XvScreenInitProc)
199706f2543Smrg	return FALSE;
200706f2543Smrg
201706f2543Smrg  if (!dixRegisterPrivateKey(&KdXVWindowKeyRec, PRIVATE_WINDOW, 0))
202706f2543Smrg      return FALSE;
203706f2543Smrg
204706f2543Smrg  if(Success != (*XvScreenInitProc)(pScreen)) return FALSE;
205706f2543Smrg
206706f2543Smrg  KdXvScreenKey = (*XvGetScreenKeyProc)();
207706f2543Smrg  PortResource = (*XvGetRTPortProc)();
208706f2543Smrg
209706f2543Smrg  pxvs = GET_XV_SCREEN(pScreen);
210706f2543Smrg
211706f2543Smrg
212706f2543Smrg  /* Anyone initializing the Xv layer must provide these two.
213706f2543Smrg     The Xv di layer calls them without even checking if they exist! */
214706f2543Smrg
215706f2543Smrg  pxvs->ddCloseScreen = KdXVCloseScreen;
216706f2543Smrg  pxvs->ddQueryAdaptors = KdXVQueryAdaptors;
217706f2543Smrg
218706f2543Smrg  /* The Xv di layer provides us with a private hook so that we don't
219706f2543Smrg     have to allocate our own screen private.  They also provide
220706f2543Smrg     a CloseScreen hook so that we don't have to wrap it.  I'm not
221706f2543Smrg     sure that I appreciate that.  */
222706f2543Smrg
223706f2543Smrg  ScreenPriv = malloc(sizeof(KdXVScreenRec));
224706f2543Smrg  pxvs->devPriv.ptr = (pointer)ScreenPriv;
225706f2543Smrg
226706f2543Smrg  if(!ScreenPriv) return FALSE;
227706f2543Smrg
228706f2543Smrg
229706f2543Smrg  ScreenPriv->CreateWindow = pScreen->CreateWindow;
230706f2543Smrg  ScreenPriv->DestroyWindow = pScreen->DestroyWindow;
231706f2543Smrg  ScreenPriv->WindowExposures = pScreen->WindowExposures;
232706f2543Smrg  ScreenPriv->ClipNotify = pScreen->ClipNotify;
233706f2543Smrg
234706f2543Smrg/*   fprintf(stderr,"XV: Wrapping screen funcs\n"); */
235706f2543Smrg
236706f2543Smrg  pScreen->CreateWindow = KdXVCreateWindow;
237706f2543Smrg  pScreen->DestroyWindow = KdXVDestroyWindow;
238706f2543Smrg  pScreen->WindowExposures = KdXVWindowExposures;
239706f2543Smrg  pScreen->ClipNotify = KdXVClipNotify;
240706f2543Smrg
241706f2543Smrg  if(!KdXVInitAdaptors(pScreen, adaptors, num))
242706f2543Smrg	return FALSE;
243706f2543Smrg
244706f2543Smrg  return TRUE;
245706f2543Smrg}
246706f2543Smrg
247706f2543Smrgstatic void
248706f2543SmrgKdXVFreeAdaptor(XvAdaptorPtr pAdaptor)
249706f2543Smrg{
250706f2543Smrg   int i;
251706f2543Smrg
252706f2543Smrg   free(pAdaptor->name);
253706f2543Smrg
254706f2543Smrg   if(pAdaptor->pEncodings) {
255706f2543Smrg      XvEncodingPtr pEncode = pAdaptor->pEncodings;
256706f2543Smrg
257706f2543Smrg      for(i = 0; i < pAdaptor->nEncodings; i++, pEncode++) {
258706f2543Smrg          free(pEncode->name);
259706f2543Smrg      }
260706f2543Smrg      free(pAdaptor->pEncodings);
261706f2543Smrg   }
262706f2543Smrg
263706f2543Smrg   free(pAdaptor->pFormats);
264706f2543Smrg
265706f2543Smrg   if(pAdaptor->pPorts) {
266706f2543Smrg      XvPortPtr pPort = pAdaptor->pPorts;
267706f2543Smrg      XvPortRecPrivatePtr pPriv;
268706f2543Smrg
269706f2543Smrg      for(i = 0; i < pAdaptor->nPorts; i++, pPort++) {
270706f2543Smrg          pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr;
271706f2543Smrg	  if(pPriv) {
272706f2543Smrg	     if(pPriv->clientClip)
273706f2543Smrg		RegionDestroy(pPriv->clientClip);
274706f2543Smrg             if(pPriv->pCompositeClip && pPriv->FreeCompositeClip)
275706f2543Smrg		RegionDestroy(pPriv->pCompositeClip);
276706f2543Smrg	     free(pPriv);
277706f2543Smrg	  }
278706f2543Smrg      }
279706f2543Smrg      free(pAdaptor->pPorts);
280706f2543Smrg   }
281706f2543Smrg
282706f2543Smrg   if(pAdaptor->nAttributes) {
283706f2543Smrg      XvAttributePtr pAttribute = pAdaptor->pAttributes;
284706f2543Smrg
285706f2543Smrg      for(i = 0; i < pAdaptor->nAttributes; i++, pAttribute++) {
286706f2543Smrg          free(pAttribute->name);
287706f2543Smrg      }
288706f2543Smrg
289706f2543Smrg      free(pAdaptor->pAttributes);
290706f2543Smrg   }
291706f2543Smrg
292706f2543Smrg   free(pAdaptor->pImages);
293706f2543Smrg
294706f2543Smrg   free(pAdaptor->devPriv.ptr);
295706f2543Smrg}
296706f2543Smrg
297706f2543Smrgstatic Bool
298706f2543SmrgKdXVInitAdaptors(
299706f2543Smrg   ScreenPtr pScreen,
300706f2543Smrg   KdVideoAdaptorPtr *infoPtr,
301706f2543Smrg   int number
302706f2543Smrg) {
303706f2543Smrg    KdScreenPriv(pScreen);
304706f2543Smrg    KdScreenInfo * screen = pScreenPriv->screen;
305706f2543Smrg
306706f2543Smrg  XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
307706f2543Smrg  KdVideoAdaptorPtr adaptorPtr;
308706f2543Smrg  XvAdaptorPtr pAdaptor, pa;
309706f2543Smrg  XvAdaptorRecPrivatePtr adaptorPriv;
310706f2543Smrg  int na, numAdaptor;
311706f2543Smrg  XvPortRecPrivatePtr portPriv;
312706f2543Smrg  XvPortPtr pPort, pp;
313706f2543Smrg  int numPort;
314706f2543Smrg  KdAttributePtr attributePtr;
315706f2543Smrg  XvAttributePtr pAttribute, pat;
316706f2543Smrg  KdVideoFormatPtr formatPtr;
317706f2543Smrg  XvFormatPtr pFormat, pf;
318706f2543Smrg  int numFormat, totFormat;
319706f2543Smrg  KdVideoEncodingPtr encodingPtr;
320706f2543Smrg  XvEncodingPtr pEncode, pe;
321706f2543Smrg  KdImagePtr imagePtr;
322706f2543Smrg  XvImagePtr pImage, pi;
323706f2543Smrg  int numVisuals;
324706f2543Smrg  VisualPtr pVisual;
325706f2543Smrg  int i;
326706f2543Smrg
327706f2543Smrg  pxvs->nAdaptors = 0;
328706f2543Smrg  pxvs->pAdaptors = NULL;
329706f2543Smrg
330706f2543Smrg  if(!(pAdaptor = calloc(number, sizeof(XvAdaptorRec))))
331706f2543Smrg      return FALSE;
332706f2543Smrg
333706f2543Smrg  for(pa = pAdaptor, na = 0, numAdaptor = 0; na < number; na++, adaptorPtr++) {
334706f2543Smrg      adaptorPtr = infoPtr[na];
335706f2543Smrg
336706f2543Smrg      if(!adaptorPtr->StopVideo || !adaptorPtr->SetPortAttribute ||
337706f2543Smrg	 !adaptorPtr->GetPortAttribute || !adaptorPtr->QueryBestSize)
338706f2543Smrg	   continue;
339706f2543Smrg
340706f2543Smrg      /* client libs expect at least one encoding */
341706f2543Smrg      if(!adaptorPtr->nEncodings || !adaptorPtr->pEncodings)
342706f2543Smrg	   continue;
343706f2543Smrg
344706f2543Smrg      pa->type = adaptorPtr->type;
345706f2543Smrg
346706f2543Smrg      if(!adaptorPtr->PutVideo && !adaptorPtr->GetVideo)
347706f2543Smrg	 pa->type &= ~XvVideoMask;
348706f2543Smrg
349706f2543Smrg      if(!adaptorPtr->PutStill && !adaptorPtr->GetStill)
350706f2543Smrg	 pa->type &= ~XvStillMask;
351706f2543Smrg
352706f2543Smrg      if(!adaptorPtr->PutImage || !adaptorPtr->QueryImageAttributes)
353706f2543Smrg	 pa->type &= ~XvImageMask;
354706f2543Smrg
355706f2543Smrg      if(!adaptorPtr->PutVideo && !adaptorPtr->PutImage &&
356706f2543Smrg							  !adaptorPtr->PutStill)
357706f2543Smrg	 pa->type &= ~XvInputMask;
358706f2543Smrg
359706f2543Smrg      if(!adaptorPtr->GetVideo && !adaptorPtr->GetStill)
360706f2543Smrg	 pa->type &= ~XvOutputMask;
361706f2543Smrg
362706f2543Smrg      if(!(adaptorPtr->type & (XvPixmapMask | XvWindowMask)))
363706f2543Smrg	  continue;
364706f2543Smrg      if(!(adaptorPtr->type & (XvImageMask | XvVideoMask | XvStillMask)))
365706f2543Smrg	  continue;
366706f2543Smrg
367706f2543Smrg      pa->pScreen = pScreen;
368706f2543Smrg      pa->ddAllocatePort = KdXVAllocatePort;
369706f2543Smrg      pa->ddFreePort = KdXVFreePort;
370706f2543Smrg      pa->ddPutVideo = KdXVPutVideo;
371706f2543Smrg      pa->ddPutStill = KdXVPutStill;
372706f2543Smrg      pa->ddGetVideo = KdXVGetVideo;
373706f2543Smrg      pa->ddGetStill = KdXVGetStill;
374706f2543Smrg      pa->ddStopVideo = KdXVStopVideo;
375706f2543Smrg      pa->ddPutImage = KdXVPutImage;
376706f2543Smrg      pa->ddSetPortAttribute = KdXVSetPortAttribute;
377706f2543Smrg      pa->ddGetPortAttribute = KdXVGetPortAttribute;
378706f2543Smrg      pa->ddQueryBestSize = KdXVQueryBestSize;
379706f2543Smrg      pa->ddQueryImageAttributes = KdXVQueryImageAttributes;
380706f2543Smrg      pa->name = strdup(adaptorPtr->name);
381706f2543Smrg
382706f2543Smrg      if(adaptorPtr->nEncodings &&
383706f2543Smrg	(pEncode = calloc(adaptorPtr->nEncodings, sizeof(XvEncodingRec)))) {
384706f2543Smrg
385706f2543Smrg	for(pe = pEncode, encodingPtr = adaptorPtr->pEncodings, i = 0;
386706f2543Smrg	    i < adaptorPtr->nEncodings; pe++, i++, encodingPtr++)
387706f2543Smrg        {
388706f2543Smrg	    pe->id = encodingPtr->id;
389706f2543Smrg	    pe->pScreen = pScreen;
390706f2543Smrg	    pe->name = strdup(encodingPtr->name);
391706f2543Smrg	    pe->width = encodingPtr->width;
392706f2543Smrg	    pe->height = encodingPtr->height;
393706f2543Smrg	    pe->rate.numerator = encodingPtr->rate.numerator;
394706f2543Smrg	    pe->rate.denominator = encodingPtr->rate.denominator;
395706f2543Smrg	}
396706f2543Smrg	pa->nEncodings = adaptorPtr->nEncodings;
397706f2543Smrg	pa->pEncodings = pEncode;
398706f2543Smrg      }
399706f2543Smrg
400706f2543Smrg      if(adaptorPtr->nImages &&
401706f2543Smrg         (pImage = calloc(adaptorPtr->nImages, sizeof(XvImageRec)))) {
402706f2543Smrg
403706f2543Smrg          for(i = 0, pi = pImage, imagePtr = adaptorPtr->pImages;
404706f2543Smrg	      i < adaptorPtr->nImages; i++, pi++, imagePtr++)
405706f2543Smrg  	  {
406706f2543Smrg	     pi->id = imagePtr->id;
407706f2543Smrg	     pi->type = imagePtr->type;
408706f2543Smrg	     pi->byte_order = imagePtr->byte_order;
409706f2543Smrg	     memcpy(pi->guid, imagePtr->guid, 16);
410706f2543Smrg	     pi->bits_per_pixel = imagePtr->bits_per_pixel;
411706f2543Smrg	     pi->format = imagePtr->format;
412706f2543Smrg	     pi->num_planes = imagePtr->num_planes;
413706f2543Smrg	     pi->depth = imagePtr->depth;
414706f2543Smrg	     pi->red_mask = imagePtr->red_mask;
415706f2543Smrg	     pi->green_mask = imagePtr->green_mask;
416706f2543Smrg	     pi->blue_mask = imagePtr->blue_mask;
417706f2543Smrg	     pi->y_sample_bits = imagePtr->y_sample_bits;
418706f2543Smrg	     pi->u_sample_bits = imagePtr->u_sample_bits;
419706f2543Smrg	     pi->v_sample_bits = imagePtr->v_sample_bits;
420706f2543Smrg	     pi->horz_y_period = imagePtr->horz_y_period;
421706f2543Smrg	     pi->horz_u_period = imagePtr->horz_u_period;
422706f2543Smrg	     pi->horz_v_period = imagePtr->horz_v_period;
423706f2543Smrg	     pi->vert_y_period = imagePtr->vert_y_period;
424706f2543Smrg	     pi->vert_u_period = imagePtr->vert_u_period;
425706f2543Smrg	     pi->vert_v_period = imagePtr->vert_v_period;
426706f2543Smrg	     memcpy(pi->component_order, imagePtr->component_order, 32);
427706f2543Smrg	     pi->scanline_order = imagePtr->scanline_order;
428706f2543Smrg          }
429706f2543Smrg	  pa->nImages = adaptorPtr->nImages;
430706f2543Smrg	  pa->pImages = pImage;
431706f2543Smrg      }
432706f2543Smrg
433706f2543Smrg      if(adaptorPtr->nAttributes &&
434706f2543Smrg	(pAttribute = calloc(adaptorPtr->nAttributes, sizeof(XvAttributeRec))))
435706f2543Smrg      {
436706f2543Smrg	for(pat = pAttribute, attributePtr = adaptorPtr->pAttributes, i = 0;
437706f2543Smrg	    i < adaptorPtr->nAttributes; pat++, i++, attributePtr++)
438706f2543Smrg        {
439706f2543Smrg	    pat->flags = attributePtr->flags;
440706f2543Smrg	    pat->min_value = attributePtr->min_value;
441706f2543Smrg	    pat->max_value = attributePtr->max_value;
442706f2543Smrg	    pat->name = strdup(attributePtr->name);
443706f2543Smrg	}
444706f2543Smrg	pa->nAttributes = adaptorPtr->nAttributes;
445706f2543Smrg	pa->pAttributes = pAttribute;
446706f2543Smrg      }
447706f2543Smrg
448706f2543Smrg
449706f2543Smrg      totFormat = adaptorPtr->nFormats;
450706f2543Smrg
451706f2543Smrg      if(!(pFormat = calloc(totFormat, sizeof(XvFormatRec)))) {
452706f2543Smrg          KdXVFreeAdaptor(pa);
453706f2543Smrg          continue;
454706f2543Smrg      }
455706f2543Smrg      for(pf = pFormat, i = 0, numFormat = 0, formatPtr = adaptorPtr->pFormats;
456706f2543Smrg	  i < adaptorPtr->nFormats; i++, formatPtr++)
457706f2543Smrg      {
458706f2543Smrg	  numVisuals = pScreen->numVisuals;
459706f2543Smrg          pVisual = pScreen->visuals;
460706f2543Smrg
461706f2543Smrg          while(numVisuals--) {
462706f2543Smrg              if((pVisual->class == formatPtr->class) &&
463706f2543Smrg                 (pVisual->nplanes == formatPtr->depth)) {
464706f2543Smrg
465706f2543Smrg		   if(numFormat >= totFormat) {
466706f2543Smrg			void *moreSpace;
467706f2543Smrg			totFormat *= 2;
468706f2543Smrg			moreSpace = realloc(pFormat,
469706f2543Smrg					     totFormat * sizeof(XvFormatRec));
470706f2543Smrg			if(!moreSpace) break;
471706f2543Smrg			pFormat = moreSpace;
472706f2543Smrg			pf = pFormat + numFormat;
473706f2543Smrg		   }
474706f2543Smrg
475706f2543Smrg                   pf->visual = pVisual->vid;
476706f2543Smrg		   pf->depth = formatPtr->depth;
477706f2543Smrg
478706f2543Smrg		   pf++;
479706f2543Smrg		   numFormat++;
480706f2543Smrg              }
481706f2543Smrg              pVisual++;
482706f2543Smrg          }
483706f2543Smrg      }
484706f2543Smrg      pa->nFormats = numFormat;
485706f2543Smrg      pa->pFormats = pFormat;
486706f2543Smrg      if(!numFormat) {
487706f2543Smrg          KdXVFreeAdaptor(pa);
488706f2543Smrg          continue;
489706f2543Smrg      }
490706f2543Smrg
491706f2543Smrg      if(!(adaptorPriv = calloc(1, sizeof(XvAdaptorRecPrivate)))) {
492706f2543Smrg          KdXVFreeAdaptor(pa);
493706f2543Smrg          continue;
494706f2543Smrg      }
495706f2543Smrg
496706f2543Smrg      adaptorPriv->flags = adaptorPtr->flags;
497706f2543Smrg      adaptorPriv->PutVideo = adaptorPtr->PutVideo;
498706f2543Smrg      adaptorPriv->PutStill = adaptorPtr->PutStill;
499706f2543Smrg      adaptorPriv->GetVideo = adaptorPtr->GetVideo;
500706f2543Smrg      adaptorPriv->GetStill = adaptorPtr->GetStill;
501706f2543Smrg      adaptorPriv->StopVideo = adaptorPtr->StopVideo;
502706f2543Smrg      adaptorPriv->SetPortAttribute = adaptorPtr->SetPortAttribute;
503706f2543Smrg      adaptorPriv->GetPortAttribute = adaptorPtr->GetPortAttribute;
504706f2543Smrg      adaptorPriv->QueryBestSize = adaptorPtr->QueryBestSize;
505706f2543Smrg      adaptorPriv->QueryImageAttributes = adaptorPtr->QueryImageAttributes;
506706f2543Smrg      adaptorPriv->PutImage = adaptorPtr->PutImage;
507706f2543Smrg      adaptorPriv->ReputImage = adaptorPtr->ReputImage;
508706f2543Smrg
509706f2543Smrg      pa->devPriv.ptr = (pointer)adaptorPriv;
510706f2543Smrg
511706f2543Smrg      if(!(pPort = calloc(adaptorPtr->nPorts, sizeof(XvPortRec)))) {
512706f2543Smrg          KdXVFreeAdaptor(pa);
513706f2543Smrg          continue;
514706f2543Smrg      }
515706f2543Smrg      for(pp = pPort, i = 0, numPort = 0;
516706f2543Smrg	  i < adaptorPtr->nPorts; i++) {
517706f2543Smrg
518706f2543Smrg          if(!(pp->id = FakeClientID(0)))
519706f2543Smrg		continue;
520706f2543Smrg
521706f2543Smrg	  if(!(portPriv = calloc(1, sizeof(XvPortRecPrivate))))
522706f2543Smrg		continue;
523706f2543Smrg
524706f2543Smrg	  if(!AddResource(pp->id, PortResource, pp)) {
525706f2543Smrg		free(portPriv);
526706f2543Smrg		continue;
527706f2543Smrg	  }
528706f2543Smrg
529706f2543Smrg          pp->pAdaptor = pa;
530706f2543Smrg          pp->pNotify = (XvPortNotifyPtr)NULL;
531706f2543Smrg          pp->pDraw = (DrawablePtr)NULL;
532706f2543Smrg          pp->client = (ClientPtr)NULL;
533706f2543Smrg          pp->grab.client = (ClientPtr)NULL;
534706f2543Smrg          pp->time = currentTime;
535706f2543Smrg          pp->devPriv.ptr = portPriv;
536706f2543Smrg
537706f2543Smrg	  portPriv->screen = screen;
538706f2543Smrg	  portPriv->AdaptorRec = adaptorPriv;
539706f2543Smrg          portPriv->DevPriv.ptr = adaptorPtr->pPortPrivates[i].ptr;
540706f2543Smrg
541706f2543Smrg          pp++;
542706f2543Smrg          numPort++;
543706f2543Smrg      }
544706f2543Smrg      pa->nPorts = numPort;
545706f2543Smrg      pa->pPorts = pPort;
546706f2543Smrg      if(!numPort) {
547706f2543Smrg          KdXVFreeAdaptor(pa);
548706f2543Smrg          continue;
549706f2543Smrg      }
550706f2543Smrg
551706f2543Smrg      pa->base_id = pPort->id;
552706f2543Smrg
553706f2543Smrg      pa++;
554706f2543Smrg      numAdaptor++;
555706f2543Smrg  }
556706f2543Smrg
557706f2543Smrg  if(numAdaptor) {
558706f2543Smrg      pxvs->nAdaptors = numAdaptor;
559706f2543Smrg      pxvs->pAdaptors = pAdaptor;
560706f2543Smrg  } else {
561706f2543Smrg     free(pAdaptor);
562706f2543Smrg     return FALSE;
563706f2543Smrg  }
564706f2543Smrg
565706f2543Smrg  return TRUE;
566706f2543Smrg}
567706f2543Smrg
568706f2543Smrg/* Video should be clipped to the intersection of the window cliplist
569706f2543Smrg   and the client cliplist specified in the GC for which the video was
570706f2543Smrg   initialized.  When we need to reclip a window, the GC that started
571706f2543Smrg   the video may not even be around anymore.  That's why we save the
572706f2543Smrg   client clip from the GC when the video is initialized.  We then
573706f2543Smrg   use KdXVUpdateCompositeClip to calculate the new composite clip
574706f2543Smrg   when we need it.  This is different from what DEC did.  They saved
575706f2543Smrg   the GC and used it's clip list when they needed to reclip the window,
576706f2543Smrg   even if the client clip was different from the one the video was
577706f2543Smrg   initialized with.  If the original GC was destroyed, they had to stop
578706f2543Smrg   the video.  I like the new method better (MArk).
579706f2543Smrg
580706f2543Smrg   This function only works for windows.  Will need to rewrite when
581706f2543Smrg   (if) we support pixmap rendering.
582706f2543Smrg*/
583706f2543Smrg
584706f2543Smrgstatic void
585706f2543SmrgKdXVUpdateCompositeClip(XvPortRecPrivatePtr portPriv)
586706f2543Smrg{
587706f2543Smrg   RegionPtr	pregWin, pCompositeClip;
588706f2543Smrg   WindowPtr	pWin;
589706f2543Smrg   Bool 	freeCompClip = FALSE;
590706f2543Smrg
591706f2543Smrg   if(portPriv->pCompositeClip)
592706f2543Smrg	return;
593706f2543Smrg
594706f2543Smrg   pWin = (WindowPtr)portPriv->pDraw;
595706f2543Smrg
596706f2543Smrg   /* get window clip list */
597706f2543Smrg   if(portPriv->subWindowMode == IncludeInferiors) {
598706f2543Smrg	pregWin = NotClippedByChildren(pWin);
599706f2543Smrg	freeCompClip = TRUE;
600706f2543Smrg   } else
601706f2543Smrg	pregWin = &pWin->clipList;
602706f2543Smrg
603706f2543Smrg   if(!portPriv->clientClip) {
604706f2543Smrg	portPriv->pCompositeClip = pregWin;
605706f2543Smrg	portPriv->FreeCompositeClip = freeCompClip;
606706f2543Smrg	return;
607706f2543Smrg   }
608706f2543Smrg
609706f2543Smrg   pCompositeClip = RegionCreate(NullBox, 1);
610706f2543Smrg   RegionCopy(pCompositeClip, portPriv->clientClip);
611706f2543Smrg   RegionTranslate(pCompositeClip,
612706f2543Smrg			portPriv->pDraw->x + portPriv->clipOrg.x,
613706f2543Smrg			portPriv->pDraw->y + portPriv->clipOrg.y);
614706f2543Smrg   RegionIntersect(pCompositeClip, pregWin, pCompositeClip);
615706f2543Smrg
616706f2543Smrg   portPriv->pCompositeClip = pCompositeClip;
617706f2543Smrg   portPriv->FreeCompositeClip = TRUE;
618706f2543Smrg
619706f2543Smrg   if(freeCompClip) {
620706f2543Smrg	RegionDestroy(pregWin);
621706f2543Smrg   }
622706f2543Smrg}
623706f2543Smrg
624706f2543Smrg/* Save the current clientClip and update the CompositeClip whenever
625706f2543Smrg   we have a fresh GC */
626706f2543Smrg
627706f2543Smrgstatic void
628706f2543SmrgKdXVCopyClip(
629706f2543Smrg   XvPortRecPrivatePtr portPriv,
630706f2543Smrg   GCPtr pGC
631706f2543Smrg){
632706f2543Smrg    /* copy the new clip if it exists */
633706f2543Smrg    if((pGC->clientClipType == CT_REGION) && pGC->clientClip) {
634706f2543Smrg	if(!portPriv->clientClip)
635706f2543Smrg	    portPriv->clientClip = RegionCreate(NullBox, 1);
636706f2543Smrg	/* Note: this is in window coordinates */
637706f2543Smrg	RegionCopy(portPriv->clientClip, pGC->clientClip);
638706f2543Smrg    } else if(portPriv->clientClip) { /* free the old clientClip */
639706f2543Smrg	RegionDestroy(portPriv->clientClip);
640706f2543Smrg	portPriv->clientClip = NULL;
641706f2543Smrg    }
642706f2543Smrg
643706f2543Smrg    /* get rid of the old clip list */
644706f2543Smrg    if(portPriv->pCompositeClip && portPriv->FreeCompositeClip) {
645706f2543Smrg	RegionDestroy(portPriv->pCompositeClip);
646706f2543Smrg    }
647706f2543Smrg
648706f2543Smrg    portPriv->clipOrg = pGC->clipOrg;
649706f2543Smrg    portPriv->pCompositeClip = pGC->pCompositeClip;
650706f2543Smrg    portPriv->FreeCompositeClip = FALSE;
651706f2543Smrg    portPriv->subWindowMode = pGC->subWindowMode;
652706f2543Smrg}
653706f2543Smrg
654706f2543Smrgstatic int
655706f2543SmrgKdXVRegetVideo(XvPortRecPrivatePtr portPriv)
656706f2543Smrg{
657706f2543Smrg  RegionRec WinRegion;
658706f2543Smrg  RegionRec ClipRegion;
659706f2543Smrg  BoxRec WinBox;
660706f2543Smrg  int ret = Success;
661706f2543Smrg  Bool clippedAway = FALSE;
662706f2543Smrg
663706f2543Smrg  KdXVUpdateCompositeClip(portPriv);
664706f2543Smrg
665706f2543Smrg  /* translate the video region to the screen */
666706f2543Smrg  WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
667706f2543Smrg  WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
668706f2543Smrg  WinBox.x2 = WinBox.x1 + portPriv->drw_w;
669706f2543Smrg  WinBox.y2 = WinBox.y1 + portPriv->drw_h;
670706f2543Smrg
671706f2543Smrg  /* clip to the window composite clip */
672706f2543Smrg  RegionInit(&WinRegion, &WinBox, 1);
673706f2543Smrg  RegionInit(&ClipRegion, NullBox, 1);
674706f2543Smrg  RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
675706f2543Smrg
676706f2543Smrg  /* that's all if it's totally obscured */
677706f2543Smrg  if(!RegionNotEmpty(&ClipRegion)) {
678706f2543Smrg	clippedAway = TRUE;
679706f2543Smrg	goto CLIP_VIDEO_BAILOUT;
680706f2543Smrg  }
681706f2543Smrg
682706f2543Smrg  if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
683706f2543Smrg     RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion);
684706f2543Smrg  }
685706f2543Smrg
686706f2543Smrg  ret = (*portPriv->AdaptorRec->GetVideo)(portPriv->screen, portPriv->pDraw,
687706f2543Smrg			portPriv->vid_x, portPriv->vid_y,
688706f2543Smrg			WinBox.x1, WinBox.y1,
689706f2543Smrg			portPriv->vid_w, portPriv->vid_h,
690706f2543Smrg			portPriv->drw_w, portPriv->drw_h,
691706f2543Smrg			&ClipRegion, portPriv->DevPriv.ptr);
692706f2543Smrg
693706f2543Smrg  if(ret == Success)
694706f2543Smrg	portPriv->isOn = XV_ON;
695706f2543Smrg
696706f2543SmrgCLIP_VIDEO_BAILOUT:
697706f2543Smrg
698706f2543Smrg  if((clippedAway || (ret != Success)) && portPriv->isOn == XV_ON) {
699706f2543Smrg	(*portPriv->AdaptorRec->StopVideo)(
700706f2543Smrg		portPriv->screen, portPriv->DevPriv.ptr, FALSE);
701706f2543Smrg	portPriv->isOn = XV_PENDING;
702706f2543Smrg  }
703706f2543Smrg
704706f2543Smrg  /* This clip was copied and only good for one shot */
705706f2543Smrg  if(!portPriv->FreeCompositeClip)
706706f2543Smrg     portPriv->pCompositeClip = NULL;
707706f2543Smrg
708706f2543Smrg  RegionUninit(&WinRegion);
709706f2543Smrg  RegionUninit(&ClipRegion);
710706f2543Smrg
711706f2543Smrg  return ret;
712706f2543Smrg}
713706f2543Smrg
714706f2543Smrg
715706f2543Smrgstatic int
716706f2543SmrgKdXVReputVideo(XvPortRecPrivatePtr portPriv)
717706f2543Smrg{
718706f2543Smrg  RegionRec WinRegion;
719706f2543Smrg  RegionRec ClipRegion;
720706f2543Smrg  BoxRec WinBox;
721706f2543Smrg  ScreenPtr pScreen = portPriv->pDraw->pScreen;
722706f2543Smrg  KdScreenPriv(pScreen);
723706f2543Smrg  KdScreenInfo *screen=pScreenPriv->screen;
724706f2543Smrg  int ret = Success;
725706f2543Smrg  Bool clippedAway = FALSE;
726706f2543Smrg
727706f2543Smrg  KdXVUpdateCompositeClip(portPriv);
728706f2543Smrg
729706f2543Smrg  /* translate the video region to the screen */
730706f2543Smrg  WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
731706f2543Smrg  WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
732706f2543Smrg  WinBox.x2 = WinBox.x1 + portPriv->drw_w;
733706f2543Smrg  WinBox.y2 = WinBox.y1 + portPriv->drw_h;
734706f2543Smrg
735706f2543Smrg  /* clip to the window composite clip */
736706f2543Smrg  RegionInit(&WinRegion, &WinBox, 1);
737706f2543Smrg  RegionInit(&ClipRegion, NullBox, 1);
738706f2543Smrg  RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
739706f2543Smrg
740706f2543Smrg  /* clip and translate to the viewport */
741706f2543Smrg  if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
742706f2543Smrg     RegionRec VPReg;
743706f2543Smrg     BoxRec VPBox;
744706f2543Smrg
745706f2543Smrg     VPBox.x1 = 0;
746706f2543Smrg     VPBox.y1 = 0;
747706f2543Smrg     VPBox.x2 = screen->width;
748706f2543Smrg     VPBox.y2 = screen->height;
749706f2543Smrg
750706f2543Smrg     RegionInit(&VPReg, &VPBox, 1);
751706f2543Smrg     RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
752706f2543Smrg     RegionUninit(&VPReg);
753706f2543Smrg  }
754706f2543Smrg
755706f2543Smrg  /* that's all if it's totally obscured */
756706f2543Smrg  if(!RegionNotEmpty(&ClipRegion)) {
757706f2543Smrg	clippedAway = TRUE;
758706f2543Smrg	goto CLIP_VIDEO_BAILOUT;
759706f2543Smrg  }
760706f2543Smrg
761706f2543Smrg  /* bailout if we have to clip but the hardware doesn't support it */
762706f2543Smrg  if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
763706f2543Smrg     BoxPtr clipBox = RegionRects(&ClipRegion);
764706f2543Smrg     if(  (RegionNumRects(&ClipRegion) != 1) ||
765706f2543Smrg	  (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
766706f2543Smrg	  (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2))
767706f2543Smrg     {
768706f2543Smrg	    clippedAway = TRUE;
769706f2543Smrg	    goto CLIP_VIDEO_BAILOUT;
770706f2543Smrg     }
771706f2543Smrg  }
772706f2543Smrg
773706f2543Smrg  if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
774706f2543Smrg     RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion);
775706f2543Smrg  }
776706f2543Smrg
777706f2543Smrg  ret = (*portPriv->AdaptorRec->PutVideo)(portPriv->screen, portPriv->pDraw,
778706f2543Smrg			portPriv->vid_x, portPriv->vid_y,
779706f2543Smrg			WinBox.x1, WinBox.y1,
780706f2543Smrg			portPriv->vid_w, portPriv->vid_h,
781706f2543Smrg			portPriv->drw_w, portPriv->drw_h,
782706f2543Smrg			&ClipRegion, portPriv->DevPriv.ptr);
783706f2543Smrg
784706f2543Smrg  if(ret == Success) portPriv->isOn = XV_ON;
785706f2543Smrg
786706f2543SmrgCLIP_VIDEO_BAILOUT:
787706f2543Smrg
788706f2543Smrg  if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
789706f2543Smrg	(*portPriv->AdaptorRec->StopVideo)(
790706f2543Smrg		portPriv->screen, portPriv->DevPriv.ptr, FALSE);
791706f2543Smrg	portPriv->isOn = XV_PENDING;
792706f2543Smrg  }
793706f2543Smrg
794706f2543Smrg  /* This clip was copied and only good for one shot */
795706f2543Smrg  if(!portPriv->FreeCompositeClip)
796706f2543Smrg     portPriv->pCompositeClip = NULL;
797706f2543Smrg
798706f2543Smrg  RegionUninit(&WinRegion);
799706f2543Smrg  RegionUninit(&ClipRegion);
800706f2543Smrg
801706f2543Smrg  return ret;
802706f2543Smrg}
803706f2543Smrg
804706f2543Smrgstatic int
805706f2543SmrgKdXVReputImage(XvPortRecPrivatePtr portPriv)
806706f2543Smrg{
807706f2543Smrg  RegionRec WinRegion;
808706f2543Smrg  RegionRec ClipRegion;
809706f2543Smrg  BoxRec WinBox;
810706f2543Smrg  ScreenPtr pScreen = portPriv->pDraw->pScreen;
811706f2543Smrg  KdScreenPriv(pScreen);
812706f2543Smrg  KdScreenInfo *screen=pScreenPriv->screen;
813706f2543Smrg  int ret = Success;
814706f2543Smrg  Bool clippedAway = FALSE;
815706f2543Smrg
816706f2543Smrg  KdXVUpdateCompositeClip(portPriv);
817706f2543Smrg
818706f2543Smrg  /* translate the video region to the screen */
819706f2543Smrg  WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
820706f2543Smrg  WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
821706f2543Smrg  WinBox.x2 = WinBox.x1 + portPriv->drw_w;
822706f2543Smrg  WinBox.y2 = WinBox.y1 + portPriv->drw_h;
823706f2543Smrg
824706f2543Smrg  /* clip to the window composite clip */
825706f2543Smrg  RegionInit(&WinRegion, &WinBox, 1);
826706f2543Smrg  RegionInit(&ClipRegion, NullBox, 1);
827706f2543Smrg  RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
828706f2543Smrg
829706f2543Smrg  /* clip and translate to the viewport */
830706f2543Smrg  if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
831706f2543Smrg     RegionRec VPReg;
832706f2543Smrg     BoxRec VPBox;
833706f2543Smrg
834706f2543Smrg     VPBox.x1 = 0;
835706f2543Smrg     VPBox.y1 = 0;
836706f2543Smrg     VPBox.x2 = screen->width;
837706f2543Smrg     VPBox.y2 = screen->height;
838706f2543Smrg
839706f2543Smrg     RegionInit(&VPReg, &VPBox, 1);
840706f2543Smrg     RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
841706f2543Smrg     RegionUninit(&VPReg);
842706f2543Smrg  }
843706f2543Smrg
844706f2543Smrg  /* that's all if it's totally obscured */
845706f2543Smrg  if(!RegionNotEmpty(&ClipRegion)) {
846706f2543Smrg	clippedAway = TRUE;
847706f2543Smrg	goto CLIP_VIDEO_BAILOUT;
848706f2543Smrg  }
849706f2543Smrg
850706f2543Smrg  /* bailout if we have to clip but the hardware doesn't support it */
851706f2543Smrg  if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
852706f2543Smrg     BoxPtr clipBox = RegionRects(&ClipRegion);
853706f2543Smrg     if(  (RegionNumRects(&ClipRegion) != 1) ||
854706f2543Smrg	  (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
855706f2543Smrg	  (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2))
856706f2543Smrg     {
857706f2543Smrg	    clippedAway = TRUE;
858706f2543Smrg	    goto CLIP_VIDEO_BAILOUT;
859706f2543Smrg     }
860706f2543Smrg  }
861706f2543Smrg
862706f2543Smrg  if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
863706f2543Smrg     RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion);
864706f2543Smrg  }
865706f2543Smrg
866706f2543Smrg  ret = (*portPriv->AdaptorRec->ReputImage)(portPriv->screen, portPriv->pDraw,
867706f2543Smrg			WinBox.x1, WinBox.y1,
868706f2543Smrg			&ClipRegion, portPriv->DevPriv.ptr);
869706f2543Smrg
870706f2543Smrg  portPriv->isOn = (ret == Success) ? XV_ON : XV_OFF;
871706f2543Smrg
872706f2543SmrgCLIP_VIDEO_BAILOUT:
873706f2543Smrg
874706f2543Smrg  if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
875706f2543Smrg	(*portPriv->AdaptorRec->StopVideo)(
876706f2543Smrg		portPriv->screen, portPriv->DevPriv.ptr, FALSE);
877706f2543Smrg	portPriv->isOn = XV_PENDING;
878706f2543Smrg  }
879706f2543Smrg
880706f2543Smrg  /* This clip was copied and only good for one shot */
881706f2543Smrg  if(!portPriv->FreeCompositeClip)
882706f2543Smrg     portPriv->pCompositeClip = NULL;
883706f2543Smrg
884706f2543Smrg  RegionUninit(&WinRegion);
885706f2543Smrg  RegionUninit(&ClipRegion);
886706f2543Smrg
887706f2543Smrg  return ret;
888706f2543Smrg}
889706f2543Smrg
890706f2543Smrg
891706f2543Smrgstatic int
892706f2543SmrgKdXVReputAllVideo(WindowPtr pWin, pointer data)
893706f2543Smrg{
894706f2543Smrg    KdXVWindowPtr WinPriv;
895706f2543Smrg
896706f2543Smrg    if (pWin->drawable.type != DRAWABLE_WINDOW)
897706f2543Smrg	return WT_DONTWALKCHILDREN;
898706f2543Smrg
899706f2543Smrg    WinPriv = GET_KDXV_WINDOW(pWin);
900706f2543Smrg
901706f2543Smrg    while(WinPriv) {
902706f2543Smrg	if(WinPriv->PortRec->type == XvInputMask)
903706f2543Smrg	    KdXVReputVideo(WinPriv->PortRec);
904706f2543Smrg	else
905706f2543Smrg	    KdXVRegetVideo(WinPriv->PortRec);
906706f2543Smrg	WinPriv = WinPriv->next;
907706f2543Smrg    }
908706f2543Smrg
909706f2543Smrg    return WT_WALKCHILDREN;
910706f2543Smrg}
911706f2543Smrg
912706f2543Smrgstatic int
913706f2543SmrgKdXVEnlistPortInWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
914706f2543Smrg{
915706f2543Smrg   KdXVWindowPtr winPriv, PrivRoot;
916706f2543Smrg
917706f2543Smrg   winPriv = PrivRoot = GET_KDXV_WINDOW(pWin);
918706f2543Smrg
919706f2543Smrg  /* Enlist our port in the window private */
920706f2543Smrg   while(winPriv) {
921706f2543Smrg	if(winPriv->PortRec == portPriv) /* we're already listed */
922706f2543Smrg	    break;
923706f2543Smrg	winPriv = winPriv->next;
924706f2543Smrg   }
925706f2543Smrg
926706f2543Smrg   if(!winPriv) {
927706f2543Smrg	winPriv = malloc(sizeof(KdXVWindowRec));
928706f2543Smrg	if(!winPriv) return BadAlloc;
929706f2543Smrg	winPriv->PortRec = portPriv;
930706f2543Smrg	winPriv->next = PrivRoot;
931706f2543Smrg	dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, winPriv);
932706f2543Smrg   }
933706f2543Smrg   return Success;
934706f2543Smrg}
935706f2543Smrg
936706f2543Smrg
937706f2543Smrgstatic void
938706f2543SmrgKdXVRemovePortFromWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
939706f2543Smrg{
940706f2543Smrg     KdXVWindowPtr winPriv, prevPriv = NULL;
941706f2543Smrg
942706f2543Smrg     winPriv = GET_KDXV_WINDOW(pWin);
943706f2543Smrg
944706f2543Smrg     while(winPriv) {
945706f2543Smrg	if(winPriv->PortRec == portPriv) {
946706f2543Smrg	    if(prevPriv)
947706f2543Smrg		prevPriv->next = winPriv->next;
948706f2543Smrg	    else
949706f2543Smrg		dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, winPriv->next);
950706f2543Smrg	    free(winPriv);
951706f2543Smrg	    break;
952706f2543Smrg	}
953706f2543Smrg	prevPriv = winPriv;
954706f2543Smrg	winPriv = winPriv->next;
955706f2543Smrg     }
956706f2543Smrg     portPriv->pDraw = NULL;
957706f2543Smrg}
958706f2543Smrg
959706f2543Smrg/****  ScreenRec fields ****/
960706f2543Smrg
961706f2543Smrg
962706f2543Smrgstatic Bool
963706f2543SmrgKdXVCreateWindow(WindowPtr pWin)
964706f2543Smrg{
965706f2543Smrg  ScreenPtr pScreen = pWin->drawable.pScreen;
966706f2543Smrg  KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
967706f2543Smrg  int ret;
968706f2543Smrg
969706f2543Smrg  pScreen->CreateWindow = ScreenPriv->CreateWindow;
970706f2543Smrg  ret = (*pScreen->CreateWindow)(pWin);
971706f2543Smrg  pScreen->CreateWindow = KdXVCreateWindow;
972706f2543Smrg
973706f2543Smrg  if (ret)
974706f2543Smrg      dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, NULL);
975706f2543Smrg
976706f2543Smrg  return ret;
977706f2543Smrg}
978706f2543Smrg
979706f2543Smrg
980706f2543Smrgstatic Bool
981706f2543SmrgKdXVDestroyWindow(WindowPtr pWin)
982706f2543Smrg{
983706f2543Smrg  ScreenPtr pScreen = pWin->drawable.pScreen;
984706f2543Smrg  KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
985706f2543Smrg  KdXVWindowPtr tmp, WinPriv = GET_KDXV_WINDOW(pWin);
986706f2543Smrg  int ret;
987706f2543Smrg
988706f2543Smrg  while(WinPriv) {
989706f2543Smrg     XvPortRecPrivatePtr pPriv = WinPriv->PortRec;
990706f2543Smrg
991706f2543Smrg     if(pPriv->isOn > XV_OFF) {
992706f2543Smrg	(*pPriv->AdaptorRec->StopVideo)(
993706f2543Smrg			pPriv->screen, pPriv->DevPriv.ptr, TRUE);
994706f2543Smrg	pPriv->isOn = XV_OFF;
995706f2543Smrg     }
996706f2543Smrg
997706f2543Smrg     pPriv->pDraw = NULL;
998706f2543Smrg     tmp = WinPriv;
999706f2543Smrg     WinPriv = WinPriv->next;
1000706f2543Smrg     free(tmp);
1001706f2543Smrg  }
1002706f2543Smrg
1003706f2543Smrg  dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, NULL);
1004706f2543Smrg
1005706f2543Smrg  pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
1006706f2543Smrg  ret = (*pScreen->DestroyWindow)(pWin);
1007706f2543Smrg  pScreen->DestroyWindow = KdXVDestroyWindow;
1008706f2543Smrg
1009706f2543Smrg  return ret;
1010706f2543Smrg}
1011706f2543Smrg
1012706f2543Smrg
1013706f2543Smrgstatic void
1014706f2543SmrgKdXVWindowExposures(WindowPtr pWin, RegionPtr reg1, RegionPtr reg2)
1015706f2543Smrg{
1016706f2543Smrg  ScreenPtr pScreen = pWin->drawable.pScreen;
1017706f2543Smrg  KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
1018706f2543Smrg  KdXVWindowPtr WinPriv = GET_KDXV_WINDOW(pWin);
1019706f2543Smrg  KdXVWindowPtr pPrev;
1020706f2543Smrg  XvPortRecPrivatePtr pPriv;
1021706f2543Smrg  Bool AreasExposed;
1022706f2543Smrg
1023706f2543Smrg  AreasExposed = (WinPriv && reg1 && RegionNotEmpty(reg1));
1024706f2543Smrg
1025706f2543Smrg  pScreen->WindowExposures = ScreenPriv->WindowExposures;
1026706f2543Smrg  (*pScreen->WindowExposures)(pWin, reg1, reg2);
1027706f2543Smrg  pScreen->WindowExposures = KdXVWindowExposures;
1028706f2543Smrg
1029706f2543Smrg  /* filter out XClearWindow/Area */
1030706f2543Smrg  if (!pWin->valdata) return;
1031706f2543Smrg
1032706f2543Smrg  pPrev = NULL;
1033706f2543Smrg
1034706f2543Smrg  while(WinPriv) {
1035706f2543Smrg     pPriv = WinPriv->PortRec;
1036706f2543Smrg
1037706f2543Smrg     /* Reput anyone with a reput function */
1038706f2543Smrg
1039706f2543Smrg     switch(pPriv->type) {
1040706f2543Smrg     case XvInputMask:
1041706f2543Smrg	KdXVReputVideo(pPriv);
1042706f2543Smrg	break;
1043706f2543Smrg     case XvOutputMask:
1044706f2543Smrg	KdXVRegetVideo(pPriv);
1045706f2543Smrg	break;
1046706f2543Smrg     default:  /* overlaid still/image*/
1047706f2543Smrg	if (pPriv->AdaptorRec->ReputImage)
1048706f2543Smrg	   KdXVReputImage(pPriv);
1049706f2543Smrg	else if(AreasExposed) {
1050706f2543Smrg	    KdXVWindowPtr tmp;
1051706f2543Smrg
1052706f2543Smrg	    if (pPriv->isOn == XV_ON) {
1053706f2543Smrg		(*pPriv->AdaptorRec->StopVideo)(
1054706f2543Smrg		    pPriv->screen, pPriv->DevPriv.ptr, FALSE);
1055706f2543Smrg		pPriv->isOn = XV_PENDING;
1056706f2543Smrg	    }
1057706f2543Smrg	    pPriv->pDraw = NULL;
1058706f2543Smrg
1059706f2543Smrg	    if(!pPrev)
1060706f2543Smrg		dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, WinPriv->next);
1061706f2543Smrg	    else
1062706f2543Smrg	       pPrev->next = WinPriv->next;
1063706f2543Smrg	    tmp = WinPriv;
1064706f2543Smrg	    WinPriv = WinPriv->next;
1065706f2543Smrg	    free(tmp);
1066706f2543Smrg	    continue;
1067706f2543Smrg	}
1068706f2543Smrg	break;
1069706f2543Smrg     }
1070706f2543Smrg     pPrev = WinPriv;
1071706f2543Smrg     WinPriv = WinPriv->next;
1072706f2543Smrg  }
1073706f2543Smrg}
1074706f2543Smrg
1075706f2543Smrg
1076706f2543Smrgstatic void
1077706f2543SmrgKdXVClipNotify(WindowPtr pWin, int dx, int dy)
1078706f2543Smrg{
1079706f2543Smrg  ScreenPtr pScreen = pWin->drawable.pScreen;
1080706f2543Smrg  KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
1081706f2543Smrg  KdXVWindowPtr WinPriv = GET_KDXV_WINDOW(pWin);
1082706f2543Smrg  KdXVWindowPtr tmp, pPrev = NULL;
1083706f2543Smrg  XvPortRecPrivatePtr pPriv;
1084706f2543Smrg  Bool visible = (pWin->visibility == VisibilityUnobscured) ||
1085706f2543Smrg		 (pWin->visibility == VisibilityPartiallyObscured);
1086706f2543Smrg
1087706f2543Smrg  while(WinPriv) {
1088706f2543Smrg     pPriv = WinPriv->PortRec;
1089706f2543Smrg
1090706f2543Smrg     if(pPriv->pCompositeClip && pPriv->FreeCompositeClip)
1091706f2543Smrg	RegionDestroy(pPriv->pCompositeClip);
1092706f2543Smrg
1093706f2543Smrg     pPriv->pCompositeClip = NULL;
1094706f2543Smrg
1095706f2543Smrg     /* Stop everything except images, but stop them too if the
1096706f2543Smrg	window isn't visible.  But we only remove the images. */
1097706f2543Smrg
1098706f2543Smrg     if(pPriv->type || !visible) {
1099706f2543Smrg	if(pPriv->isOn == XV_ON) {
1100706f2543Smrg	    (*pPriv->AdaptorRec->StopVideo)(
1101706f2543Smrg			pPriv->screen, pPriv->DevPriv.ptr, FALSE);
1102706f2543Smrg	    pPriv->isOn = XV_PENDING;
1103706f2543Smrg	}
1104706f2543Smrg
1105706f2543Smrg	if(!pPriv->type) {  /* overlaid still/image */
1106706f2543Smrg	    pPriv->pDraw = NULL;
1107706f2543Smrg
1108706f2543Smrg	    if(!pPrev)
1109706f2543Smrg		dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, WinPriv->next);
1110706f2543Smrg	    else
1111706f2543Smrg	       pPrev->next = WinPriv->next;
1112706f2543Smrg	    tmp = WinPriv;
1113706f2543Smrg	    WinPriv = WinPriv->next;
1114706f2543Smrg	    free(tmp);
1115706f2543Smrg	    continue;
1116706f2543Smrg	}
1117706f2543Smrg     }
1118706f2543Smrg
1119706f2543Smrg     pPrev = WinPriv;
1120706f2543Smrg     WinPriv = WinPriv->next;
1121706f2543Smrg  }
1122706f2543Smrg
1123706f2543Smrg  if(ScreenPriv->ClipNotify) {
1124706f2543Smrg      pScreen->ClipNotify = ScreenPriv->ClipNotify;
1125706f2543Smrg      (*pScreen->ClipNotify)(pWin, dx, dy);
1126706f2543Smrg      pScreen->ClipNotify = KdXVClipNotify;
1127706f2543Smrg  }
1128706f2543Smrg}
1129706f2543Smrg
1130706f2543Smrg
1131706f2543Smrg
1132706f2543Smrg/**** Required XvScreenRec fields ****/
1133706f2543Smrg
1134706f2543Smrgstatic Bool
1135706f2543SmrgKdXVCloseScreen(int i, ScreenPtr pScreen)
1136706f2543Smrg{
1137706f2543Smrg  XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
1138706f2543Smrg  KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
1139706f2543Smrg  XvAdaptorPtr pa;
1140706f2543Smrg  int c;
1141706f2543Smrg
1142706f2543Smrg  if(!ScreenPriv) return TRUE;
1143706f2543Smrg
1144706f2543Smrg  pScreen->CreateWindow = ScreenPriv->CreateWindow;
1145706f2543Smrg  pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
1146706f2543Smrg  pScreen->WindowExposures = ScreenPriv->WindowExposures;
1147706f2543Smrg  pScreen->ClipNotify = ScreenPriv->ClipNotify;
1148706f2543Smrg
1149706f2543Smrg/*   fprintf(stderr,"XV: Unwrapping screen funcs\n"); */
1150706f2543Smrg
1151706f2543Smrg  for(c = 0, pa = pxvs->pAdaptors; c < pxvs->nAdaptors; c++, pa++) {
1152706f2543Smrg       KdXVFreeAdaptor(pa);
1153706f2543Smrg  }
1154706f2543Smrg
1155706f2543Smrg  free(pxvs->pAdaptors);
1156706f2543Smrg  free(ScreenPriv);
1157706f2543Smrg
1158706f2543Smrg  return TRUE;
1159706f2543Smrg}
1160706f2543Smrg
1161706f2543Smrg
1162706f2543Smrgstatic int
1163706f2543SmrgKdXVQueryAdaptors(
1164706f2543Smrg   ScreenPtr pScreen,
1165706f2543Smrg   XvAdaptorPtr *p_pAdaptors,
1166706f2543Smrg   int *p_nAdaptors
1167706f2543Smrg){
1168706f2543Smrg  XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
1169706f2543Smrg
1170706f2543Smrg  *p_nAdaptors = pxvs->nAdaptors;
1171706f2543Smrg  *p_pAdaptors = pxvs->pAdaptors;
1172706f2543Smrg
1173706f2543Smrg  return Success;
1174706f2543Smrg}
1175706f2543Smrg
1176706f2543Smrgstatic Bool
1177706f2543SmrgKdXVRunning (ScreenPtr pScreen)
1178706f2543Smrg{
1179706f2543Smrg    return (KdXVGeneration == serverGeneration &&
1180706f2543Smrg	    GET_XV_SCREEN(pScreen) != 0);
1181706f2543Smrg}
1182706f2543Smrg
1183706f2543SmrgBool
1184706f2543SmrgKdXVEnable(ScreenPtr pScreen)
1185706f2543Smrg{
1186706f2543Smrg    if (!KdXVRunning (pScreen))
1187706f2543Smrg	return TRUE;
1188706f2543Smrg
1189706f2543Smrg    WalkTree(pScreen, KdXVReputAllVideo, 0);
1190706f2543Smrg
1191706f2543Smrg    return TRUE;
1192706f2543Smrg}
1193706f2543Smrg
1194706f2543Smrgvoid
1195706f2543SmrgKdXVDisable(ScreenPtr pScreen)
1196706f2543Smrg{
1197706f2543Smrg    XvScreenPtr pxvs;
1198706f2543Smrg    KdXVScreenPtr ScreenPriv;
1199706f2543Smrg    XvAdaptorPtr pAdaptor;
1200706f2543Smrg    XvPortPtr pPort;
1201706f2543Smrg    XvPortRecPrivatePtr pPriv;
1202706f2543Smrg    int i, j;
1203706f2543Smrg
1204706f2543Smrg    if (!KdXVRunning (pScreen))
1205706f2543Smrg	return;
1206706f2543Smrg
1207706f2543Smrg    pxvs = GET_XV_SCREEN(pScreen);
1208706f2543Smrg    ScreenPriv = GET_KDXV_SCREEN(pScreen);
1209706f2543Smrg
1210706f2543Smrg    for(i = 0; i < pxvs->nAdaptors; i++) {
1211706f2543Smrg	pAdaptor = &pxvs->pAdaptors[i];
1212706f2543Smrg	for(j = 0; j < pAdaptor->nPorts; j++) {
1213706f2543Smrg	    pPort = &pAdaptor->pPorts[j];
1214706f2543Smrg	    pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr;
1215706f2543Smrg	    if(pPriv->isOn > XV_OFF) {
1216706f2543Smrg
1217706f2543Smrg		(*pPriv->AdaptorRec->StopVideo)(
1218706f2543Smrg			pPriv->screen, pPriv->DevPriv.ptr, TRUE);
1219706f2543Smrg		pPriv->isOn = XV_OFF;
1220706f2543Smrg
1221706f2543Smrg		if(pPriv->pCompositeClip && pPriv->FreeCompositeClip)
1222706f2543Smrg		    RegionDestroy(pPriv->pCompositeClip);
1223706f2543Smrg
1224706f2543Smrg		pPriv->pCompositeClip = NULL;
1225706f2543Smrg
1226706f2543Smrg		if(!pPriv->type && pPriv->pDraw) { /* still */
1227706f2543Smrg		    KdXVRemovePortFromWindow((WindowPtr)pPriv->pDraw, pPriv);
1228706f2543Smrg		}
1229706f2543Smrg	    }
1230706f2543Smrg	}
1231706f2543Smrg    }
1232706f2543Smrg}
1233706f2543Smrg
1234706f2543Smrg/**** XvAdaptorRec fields ****/
1235706f2543Smrg
1236706f2543Smrgstatic int
1237706f2543SmrgKdXVAllocatePort(
1238706f2543Smrg   unsigned long port,
1239706f2543Smrg   XvPortPtr pPort,
1240706f2543Smrg   XvPortPtr *ppPort
1241706f2543Smrg){
1242706f2543Smrg  *ppPort = pPort;
1243706f2543Smrg  return Success;
1244706f2543Smrg}
1245706f2543Smrg
1246706f2543Smrgstatic int
1247706f2543SmrgKdXVFreePort(XvPortPtr pPort)
1248706f2543Smrg{
1249706f2543Smrg  return Success;
1250706f2543Smrg}
1251706f2543Smrg
1252706f2543Smrgstatic int
1253706f2543SmrgKdXVPutVideo(
1254706f2543Smrg   ClientPtr client,
1255706f2543Smrg   DrawablePtr pDraw,
1256706f2543Smrg   XvPortPtr pPort,
1257706f2543Smrg   GCPtr pGC,
1258706f2543Smrg   INT16 vid_x, INT16 vid_y,
1259706f2543Smrg   CARD16 vid_w, CARD16 vid_h,
1260706f2543Smrg   INT16 drw_x, INT16 drw_y,
1261706f2543Smrg   CARD16 drw_w, CARD16 drw_h
1262706f2543Smrg){
1263706f2543Smrg  XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
1264706f2543Smrg  KdScreenPriv(portPriv->screen->pScreen);
1265706f2543Smrg  int result;
1266706f2543Smrg
1267706f2543Smrg  /* No dumping video to pixmaps... For now anyhow */
1268706f2543Smrg  if(pDraw->type != DRAWABLE_WINDOW) {
1269706f2543Smrg      pPort->pDraw = (DrawablePtr)NULL;
1270706f2543Smrg      return BadAlloc;
1271706f2543Smrg  }
1272706f2543Smrg
1273706f2543Smrg  /* If we are changing windows, unregister our port in the old window */
1274706f2543Smrg  if(portPriv->pDraw && (portPriv->pDraw != pDraw))
1275706f2543Smrg     KdXVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
1276706f2543Smrg
1277706f2543Smrg  /* Register our port with the new window */
1278706f2543Smrg  result =  KdXVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
1279706f2543Smrg  if(result != Success) return result;
1280706f2543Smrg
1281706f2543Smrg  portPriv->pDraw = pDraw;
1282706f2543Smrg  portPriv->type = XvInputMask;
1283706f2543Smrg
1284706f2543Smrg  /* save a copy of these parameters */
1285706f2543Smrg  portPriv->vid_x = vid_x;  portPriv->vid_y = vid_y;
1286706f2543Smrg  portPriv->vid_w = vid_w;  portPriv->vid_h = vid_h;
1287706f2543Smrg  portPriv->drw_x = drw_x;  portPriv->drw_y = drw_y;
1288706f2543Smrg  portPriv->drw_w = drw_w;  portPriv->drw_h = drw_h;
1289706f2543Smrg
1290706f2543Smrg  /* make sure we have the most recent copy of the clientClip */
1291706f2543Smrg  KdXVCopyClip(portPriv, pGC);
1292706f2543Smrg
1293706f2543Smrg  /* To indicate to the DI layer that we were successful */
1294706f2543Smrg  pPort->pDraw = pDraw;
1295706f2543Smrg
1296706f2543Smrg  if (!pScreenPriv->enabled) return Success;
1297706f2543Smrg
1298706f2543Smrg  return(KdXVReputVideo(portPriv));
1299706f2543Smrg}
1300706f2543Smrg
1301706f2543Smrgstatic int
1302706f2543SmrgKdXVPutStill(
1303706f2543Smrg   ClientPtr client,
1304706f2543Smrg   DrawablePtr pDraw,
1305706f2543Smrg   XvPortPtr pPort,
1306706f2543Smrg   GCPtr pGC,
1307706f2543Smrg   INT16 vid_x, INT16 vid_y,
1308706f2543Smrg   CARD16 vid_w, CARD16 vid_h,
1309706f2543Smrg   INT16 drw_x, INT16 drw_y,
1310706f2543Smrg   CARD16 drw_w, CARD16 drw_h
1311706f2543Smrg){
1312706f2543Smrg  XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
1313706f2543Smrg  ScreenPtr pScreen = pDraw->pScreen;
1314706f2543Smrg  KdScreenPriv(pScreen);
1315706f2543Smrg  KdScreenInfo *screen=pScreenPriv->screen;
1316706f2543Smrg  RegionRec WinRegion;
1317706f2543Smrg  RegionRec ClipRegion;
1318706f2543Smrg  BoxRec WinBox;
1319706f2543Smrg  int ret = Success;
1320706f2543Smrg  Bool clippedAway = FALSE;
1321706f2543Smrg
1322706f2543Smrg  if (pDraw->type != DRAWABLE_WINDOW)
1323706f2543Smrg      return BadAlloc;
1324706f2543Smrg
1325706f2543Smrg  if (!pScreenPriv->enabled) return Success;
1326706f2543Smrg
1327706f2543Smrg  WinBox.x1 = pDraw->x + drw_x;
1328706f2543Smrg  WinBox.y1 = pDraw->y + drw_y;
1329706f2543Smrg  WinBox.x2 = WinBox.x1 + drw_w;
1330706f2543Smrg  WinBox.y2 = WinBox.y1 + drw_h;
1331706f2543Smrg
1332706f2543Smrg  RegionInit(&WinRegion, &WinBox, 1);
1333706f2543Smrg  RegionInit(&ClipRegion, NullBox, 1);
1334706f2543Smrg  RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
1335706f2543Smrg
1336706f2543Smrg  if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
1337706f2543Smrg     RegionRec VPReg;
1338706f2543Smrg     BoxRec VPBox;
1339706f2543Smrg
1340706f2543Smrg     VPBox.x1 = 0;
1341706f2543Smrg     VPBox.y1 = 0;
1342706f2543Smrg     VPBox.x2 = screen->width;
1343706f2543Smrg     VPBox.y2 = screen->height;
1344706f2543Smrg
1345706f2543Smrg     RegionInit(&VPReg, &VPBox, 1);
1346706f2543Smrg     RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
1347706f2543Smrg     RegionUninit(&VPReg);
1348706f2543Smrg  }
1349706f2543Smrg
1350706f2543Smrg  if(portPriv->pDraw) {
1351706f2543Smrg     KdXVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
1352706f2543Smrg  }
1353706f2543Smrg
1354706f2543Smrg  if(!RegionNotEmpty(&ClipRegion)) {
1355706f2543Smrg     clippedAway = TRUE;
1356706f2543Smrg     goto PUT_STILL_BAILOUT;
1357706f2543Smrg  }
1358706f2543Smrg
1359706f2543Smrg  if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
1360706f2543Smrg     BoxPtr clipBox = RegionRects(&ClipRegion);
1361706f2543Smrg     if(  (RegionNumRects(&ClipRegion) != 1) ||
1362706f2543Smrg	  (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
1363706f2543Smrg	  (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2))
1364706f2543Smrg     {
1365706f2543Smrg	  clippedAway = TRUE;
1366706f2543Smrg          goto PUT_STILL_BAILOUT;
1367706f2543Smrg     }
1368706f2543Smrg  }
1369706f2543Smrg
1370706f2543Smrg  if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
1371706f2543Smrg     RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion);
1372706f2543Smrg  }
1373706f2543Smrg
1374706f2543Smrg  ret = (*portPriv->AdaptorRec->PutStill)(portPriv->screen, pDraw,
1375706f2543Smrg		vid_x, vid_y, WinBox.x1, WinBox.y1,
1376706f2543Smrg		vid_w, vid_h, drw_w, drw_h,
1377706f2543Smrg		&ClipRegion, portPriv->DevPriv.ptr);
1378706f2543Smrg
1379706f2543Smrg  if((ret == Success) &&
1380706f2543Smrg	(portPriv->AdaptorRec->flags & VIDEO_OVERLAID_STILLS)) {
1381706f2543Smrg
1382706f2543Smrg     KdXVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
1383706f2543Smrg     portPriv->isOn = XV_ON;
1384706f2543Smrg     portPriv->pDraw = pDraw;
1385706f2543Smrg     portPriv->drw_x = drw_x;  portPriv->drw_y = drw_y;
1386706f2543Smrg     portPriv->drw_w = drw_w;  portPriv->drw_h = drw_h;
1387706f2543Smrg     portPriv->type = 0;  /* no mask means it's transient and should
1388706f2543Smrg			     not be reput once it's removed */
1389706f2543Smrg     pPort->pDraw = pDraw;  /* make sure we can get stop requests */
1390706f2543Smrg  }
1391706f2543Smrg
1392706f2543SmrgPUT_STILL_BAILOUT:
1393706f2543Smrg
1394706f2543Smrg  if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
1395706f2543Smrg        (*portPriv->AdaptorRec->StopVideo)(
1396706f2543Smrg                portPriv->screen, portPriv->DevPriv.ptr, FALSE);
1397706f2543Smrg        portPriv->isOn = XV_PENDING;
1398706f2543Smrg  }
1399706f2543Smrg
1400706f2543Smrg  RegionUninit(&WinRegion);
1401706f2543Smrg  RegionUninit(&ClipRegion);
1402706f2543Smrg
1403706f2543Smrg  return ret;
1404706f2543Smrg}
1405706f2543Smrg
1406706f2543Smrgstatic int
1407706f2543SmrgKdXVGetVideo(
1408706f2543Smrg   ClientPtr client,
1409706f2543Smrg   DrawablePtr pDraw,
1410706f2543Smrg   XvPortPtr pPort,
1411706f2543Smrg   GCPtr pGC,
1412706f2543Smrg   INT16 vid_x, INT16 vid_y,
1413706f2543Smrg   CARD16 vid_w, CARD16 vid_h,
1414706f2543Smrg   INT16 drw_x, INT16 drw_y,
1415706f2543Smrg   CARD16 drw_w, CARD16 drw_h
1416706f2543Smrg){
1417706f2543Smrg  XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
1418706f2543Smrg  int result;
1419706f2543Smrg  KdScreenPriv(portPriv->screen->pScreen);
1420706f2543Smrg
1421706f2543Smrg  /* No pixmaps... For now anyhow */
1422706f2543Smrg  if(pDraw->type != DRAWABLE_WINDOW) {
1423706f2543Smrg      pPort->pDraw = (DrawablePtr)NULL;
1424706f2543Smrg      return BadAlloc;
1425706f2543Smrg  }
1426706f2543Smrg
1427706f2543Smrg  /* If we are changing windows, unregister our port in the old window */
1428706f2543Smrg  if(portPriv->pDraw && (portPriv->pDraw != pDraw))
1429706f2543Smrg     KdXVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
1430706f2543Smrg
1431706f2543Smrg  /* Register our port with the new window */
1432706f2543Smrg  result =  KdXVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
1433706f2543Smrg  if(result != Success) return result;
1434706f2543Smrg
1435706f2543Smrg  portPriv->pDraw = pDraw;
1436706f2543Smrg  portPriv->type = XvOutputMask;
1437706f2543Smrg
1438706f2543Smrg  /* save a copy of these parameters */
1439706f2543Smrg  portPriv->vid_x = vid_x;  portPriv->vid_y = vid_y;
1440706f2543Smrg  portPriv->vid_w = vid_w;  portPriv->vid_h = vid_h;
1441706f2543Smrg  portPriv->drw_x = drw_x;  portPriv->drw_y = drw_y;
1442706f2543Smrg  portPriv->drw_w = drw_w;  portPriv->drw_h = drw_h;
1443706f2543Smrg
1444706f2543Smrg  /* make sure we have the most recent copy of the clientClip */
1445706f2543Smrg  KdXVCopyClip(portPriv, pGC);
1446706f2543Smrg
1447706f2543Smrg  /* To indicate to the DI layer that we were successful */
1448706f2543Smrg  pPort->pDraw = pDraw;
1449706f2543Smrg
1450706f2543Smrg  if(!pScreenPriv->enabled) return Success;
1451706f2543Smrg
1452706f2543Smrg  return(KdXVRegetVideo(portPriv));
1453706f2543Smrg}
1454706f2543Smrg
1455706f2543Smrgstatic int
1456706f2543SmrgKdXVGetStill(
1457706f2543Smrg   ClientPtr client,
1458706f2543Smrg   DrawablePtr pDraw,
1459706f2543Smrg   XvPortPtr pPort,
1460706f2543Smrg   GCPtr pGC,
1461706f2543Smrg   INT16 vid_x, INT16 vid_y,
1462706f2543Smrg   CARD16 vid_w, CARD16 vid_h,
1463706f2543Smrg   INT16 drw_x, INT16 drw_y,
1464706f2543Smrg   CARD16 drw_w, CARD16 drw_h
1465706f2543Smrg){
1466706f2543Smrg  XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
1467706f2543Smrg  ScreenPtr pScreen = pDraw->pScreen;
1468706f2543Smrg  KdScreenPriv(pScreen);
1469706f2543Smrg  RegionRec WinRegion;
1470706f2543Smrg  RegionRec ClipRegion;
1471706f2543Smrg  BoxRec WinBox;
1472706f2543Smrg  int ret = Success;
1473706f2543Smrg  Bool clippedAway = FALSE;
1474706f2543Smrg
1475706f2543Smrg  if (pDraw->type != DRAWABLE_WINDOW)
1476706f2543Smrg      return BadAlloc;
1477706f2543Smrg
1478706f2543Smrg  if(!pScreenPriv->enabled) return Success;
1479706f2543Smrg
1480706f2543Smrg  WinBox.x1 = pDraw->x + drw_x;
1481706f2543Smrg  WinBox.y1 = pDraw->y + drw_y;
1482706f2543Smrg  WinBox.x2 = WinBox.x1 + drw_w;
1483706f2543Smrg  WinBox.y2 = WinBox.y1 + drw_h;
1484706f2543Smrg
1485706f2543Smrg  RegionInit(&WinRegion, &WinBox, 1);
1486706f2543Smrg  RegionInit(&ClipRegion, NullBox, 1);
1487706f2543Smrg  RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
1488706f2543Smrg
1489706f2543Smrg  if(portPriv->pDraw) {
1490706f2543Smrg     KdXVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
1491706f2543Smrg  }
1492706f2543Smrg
1493706f2543Smrg  if(!RegionNotEmpty(&ClipRegion)) {
1494706f2543Smrg     clippedAway = TRUE;
1495706f2543Smrg     goto GET_STILL_BAILOUT;
1496706f2543Smrg  }
1497706f2543Smrg
1498706f2543Smrg  if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
1499706f2543Smrg     RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion);
1500706f2543Smrg  }
1501706f2543Smrg
1502706f2543Smrg  ret = (*portPriv->AdaptorRec->GetStill)(portPriv->screen, pDraw,
1503706f2543Smrg		vid_x, vid_y, WinBox.x1, WinBox.y1,
1504706f2543Smrg		vid_w, vid_h, drw_w, drw_h,
1505706f2543Smrg		&ClipRegion, portPriv->DevPriv.ptr);
1506706f2543Smrg
1507706f2543SmrgGET_STILL_BAILOUT:
1508706f2543Smrg
1509706f2543Smrg  if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
1510706f2543Smrg        (*portPriv->AdaptorRec->StopVideo)(
1511706f2543Smrg                portPriv->screen, portPriv->DevPriv.ptr, FALSE);
1512706f2543Smrg        portPriv->isOn = XV_PENDING;
1513706f2543Smrg  }
1514706f2543Smrg
1515706f2543Smrg  RegionUninit(&WinRegion);
1516706f2543Smrg  RegionUninit(&ClipRegion);
1517706f2543Smrg
1518706f2543Smrg  return ret;
1519706f2543Smrg}
1520706f2543Smrg
1521706f2543Smrg
1522706f2543Smrg
1523706f2543Smrgstatic int
1524706f2543SmrgKdXVStopVideo(
1525706f2543Smrg   ClientPtr client,
1526706f2543Smrg   XvPortPtr pPort,
1527706f2543Smrg   DrawablePtr pDraw
1528706f2543Smrg){
1529706f2543Smrg  XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
1530706f2543Smrg  KdScreenPriv(portPriv->screen->pScreen);
1531706f2543Smrg
1532706f2543Smrg  if(pDraw->type != DRAWABLE_WINDOW)
1533706f2543Smrg      return BadAlloc;
1534706f2543Smrg
1535706f2543Smrg  KdXVRemovePortFromWindow((WindowPtr)pDraw, portPriv);
1536706f2543Smrg
1537706f2543Smrg  if(!pScreenPriv->enabled) return Success;
1538706f2543Smrg
1539706f2543Smrg  /* Must free resources. */
1540706f2543Smrg
1541706f2543Smrg  if(portPriv->isOn > XV_OFF) {
1542706f2543Smrg	(*portPriv->AdaptorRec->StopVideo)(
1543706f2543Smrg		portPriv->screen, portPriv->DevPriv.ptr, TRUE);
1544706f2543Smrg	portPriv->isOn = XV_OFF;
1545706f2543Smrg  }
1546706f2543Smrg
1547706f2543Smrg  return Success;
1548706f2543Smrg}
1549706f2543Smrg
1550706f2543Smrgstatic int
1551706f2543SmrgKdXVSetPortAttribute(
1552706f2543Smrg   ClientPtr client,
1553706f2543Smrg   XvPortPtr pPort,
1554706f2543Smrg   Atom attribute,
1555706f2543Smrg   INT32 value
1556706f2543Smrg){
1557706f2543Smrg  XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
1558706f2543Smrg
1559706f2543Smrg  return((*portPriv->AdaptorRec->SetPortAttribute)(portPriv->screen,
1560706f2543Smrg		attribute, value, portPriv->DevPriv.ptr));
1561706f2543Smrg}
1562706f2543Smrg
1563706f2543Smrg
1564706f2543Smrgstatic int
1565706f2543SmrgKdXVGetPortAttribute(
1566706f2543Smrg   ClientPtr client,
1567706f2543Smrg   XvPortPtr pPort,
1568706f2543Smrg   Atom attribute,
1569706f2543Smrg   INT32 *p_value
1570706f2543Smrg){
1571706f2543Smrg  XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
1572706f2543Smrg
1573706f2543Smrg  return((*portPriv->AdaptorRec->GetPortAttribute)(portPriv->screen,
1574706f2543Smrg		attribute, (int *) p_value, portPriv->DevPriv.ptr));
1575706f2543Smrg}
1576706f2543Smrg
1577706f2543Smrg
1578706f2543Smrg
1579706f2543Smrgstatic int
1580706f2543SmrgKdXVQueryBestSize(
1581706f2543Smrg   ClientPtr client,
1582706f2543Smrg   XvPortPtr pPort,
1583706f2543Smrg   CARD8 motion,
1584706f2543Smrg   CARD16 vid_w, CARD16 vid_h,
1585706f2543Smrg   CARD16 drw_w, CARD16 drw_h,
1586706f2543Smrg   unsigned int *p_w, unsigned int *p_h
1587706f2543Smrg){
1588706f2543Smrg  XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
1589706f2543Smrg
1590706f2543Smrg  (*portPriv->AdaptorRec->QueryBestSize)(portPriv->screen,
1591706f2543Smrg		(Bool)motion, vid_w, vid_h, drw_w, drw_h,
1592706f2543Smrg		p_w, p_h, portPriv->DevPriv.ptr);
1593706f2543Smrg
1594706f2543Smrg  return Success;
1595706f2543Smrg}
1596706f2543Smrg
1597706f2543Smrg
1598706f2543Smrgstatic int
1599706f2543SmrgKdXVPutImage(
1600706f2543Smrg   ClientPtr client,
1601706f2543Smrg   DrawablePtr pDraw,
1602706f2543Smrg   XvPortPtr pPort,
1603706f2543Smrg   GCPtr pGC,
1604706f2543Smrg   INT16 src_x, INT16 src_y,
1605706f2543Smrg   CARD16 src_w, CARD16 src_h,
1606706f2543Smrg   INT16 drw_x, INT16 drw_y,
1607706f2543Smrg   CARD16 drw_w, CARD16 drw_h,
1608706f2543Smrg   XvImagePtr format,
1609706f2543Smrg   unsigned char* data,
1610706f2543Smrg   Bool sync,
1611706f2543Smrg   CARD16 width, CARD16 height
1612706f2543Smrg){
1613706f2543Smrg  XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
1614706f2543Smrg  ScreenPtr pScreen = pDraw->pScreen;
1615706f2543Smrg  KdScreenPriv(pScreen);
1616706f2543Smrg  RegionRec WinRegion;
1617706f2543Smrg  RegionRec ClipRegion;
1618706f2543Smrg  BoxRec WinBox;
1619706f2543Smrg  int ret = Success;
1620706f2543Smrg  Bool clippedAway = FALSE;
1621706f2543Smrg
1622706f2543Smrg  if (pDraw->type != DRAWABLE_WINDOW)
1623706f2543Smrg      return BadAlloc;
1624706f2543Smrg
1625706f2543Smrg  if(!pScreenPriv->enabled) return Success;
1626706f2543Smrg
1627706f2543Smrg  WinBox.x1 = pDraw->x + drw_x;
1628706f2543Smrg  WinBox.y1 = pDraw->y + drw_y;
1629706f2543Smrg  WinBox.x2 = WinBox.x1 + drw_w;
1630706f2543Smrg  WinBox.y2 = WinBox.y1 + drw_h;
1631706f2543Smrg
1632706f2543Smrg  RegionInit(&WinRegion, &WinBox, 1);
1633706f2543Smrg  RegionInit(&ClipRegion, NullBox, 1);
1634706f2543Smrg  RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
1635706f2543Smrg
1636706f2543Smrg  if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
1637706f2543Smrg     RegionRec VPReg;
1638706f2543Smrg     BoxRec VPBox;
1639706f2543Smrg
1640706f2543Smrg     VPBox.x1 = 0;
1641706f2543Smrg     VPBox.y1 = 0;
1642706f2543Smrg     VPBox.x2 = pScreen->width;
1643706f2543Smrg     VPBox.y2 = pScreen->height;
1644706f2543Smrg
1645706f2543Smrg     RegionInit(&VPReg, &VPBox, 1);
1646706f2543Smrg     RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
1647706f2543Smrg     RegionUninit(&VPReg);
1648706f2543Smrg  }
1649706f2543Smrg
1650706f2543Smrg  if(portPriv->pDraw) {
1651706f2543Smrg     KdXVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
1652706f2543Smrg  }
1653706f2543Smrg
1654706f2543Smrg  if(!RegionNotEmpty(&ClipRegion)) {
1655706f2543Smrg     clippedAway = TRUE;
1656706f2543Smrg     goto PUT_IMAGE_BAILOUT;
1657706f2543Smrg  }
1658706f2543Smrg
1659706f2543Smrg  if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
1660706f2543Smrg     BoxPtr clipBox = RegionRects(&ClipRegion);
1661706f2543Smrg     if(  (RegionNumRects(&ClipRegion) != 1) ||
1662706f2543Smrg	  (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
1663706f2543Smrg	  (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2))
1664706f2543Smrg     {
1665706f2543Smrg	  clippedAway = TRUE;
1666706f2543Smrg          goto PUT_IMAGE_BAILOUT;
1667706f2543Smrg     }
1668706f2543Smrg  }
1669706f2543Smrg
1670706f2543Smrg  if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
1671706f2543Smrg     RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion);
1672706f2543Smrg  }
1673706f2543Smrg
1674706f2543Smrg  ret = (*portPriv->AdaptorRec->PutImage)(portPriv->screen, pDraw,
1675706f2543Smrg		src_x, src_y, WinBox.x1, WinBox.y1,
1676706f2543Smrg		src_w, src_h, drw_w, drw_h, format->id, data, width, height,
1677706f2543Smrg		sync, &ClipRegion, portPriv->DevPriv.ptr);
1678706f2543Smrg
1679706f2543Smrg  if((ret == Success) &&
1680706f2543Smrg	(portPriv->AdaptorRec->flags & VIDEO_OVERLAID_IMAGES)) {
1681706f2543Smrg
1682706f2543Smrg     KdXVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
1683706f2543Smrg     portPriv->isOn = XV_ON;
1684706f2543Smrg     portPriv->pDraw = pDraw;
1685706f2543Smrg     portPriv->drw_x = drw_x;  portPriv->drw_y = drw_y;
1686706f2543Smrg     portPriv->drw_w = drw_w;  portPriv->drw_h = drw_h;
1687706f2543Smrg     portPriv->type = 0;  /* no mask means it's transient and should
1688706f2543Smrg			     not be reput once it's removed */
1689706f2543Smrg     pPort->pDraw = pDraw;  /* make sure we can get stop requests */
1690706f2543Smrg  }
1691706f2543Smrg
1692706f2543SmrgPUT_IMAGE_BAILOUT:
1693706f2543Smrg
1694706f2543Smrg  if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
1695706f2543Smrg        (*portPriv->AdaptorRec->StopVideo)(
1696706f2543Smrg                portPriv->screen, portPriv->DevPriv.ptr, FALSE);
1697706f2543Smrg        portPriv->isOn = XV_PENDING;
1698706f2543Smrg  }
1699706f2543Smrg
1700706f2543Smrg  RegionUninit(&WinRegion);
1701706f2543Smrg  RegionUninit(&ClipRegion);
1702706f2543Smrg
1703706f2543Smrg  return ret;
1704706f2543Smrg}
1705706f2543Smrg
1706706f2543Smrg
1707706f2543Smrgstatic  int
1708706f2543SmrgKdXVQueryImageAttributes(
1709706f2543Smrg   ClientPtr client,
1710706f2543Smrg   XvPortPtr pPort,
1711706f2543Smrg   XvImagePtr format,
1712706f2543Smrg   CARD16 *width,
1713706f2543Smrg   CARD16 *height,
1714706f2543Smrg   int *pitches,
1715706f2543Smrg   int *offsets
1716706f2543Smrg){
1717706f2543Smrg  XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
1718706f2543Smrg
1719706f2543Smrg  return (*portPriv->AdaptorRec->QueryImageAttributes)(portPriv->screen,
1720706f2543Smrg			format->id, width, height, pitches, offsets);
1721706f2543Smrg}
1722706f2543Smrg
1723706f2543Smrg
1724706f2543Smrg/****************  Common video manipulation functions *******************/
1725706f2543Smrg
1726706f2543Smrgvoid
1727706f2543SmrgKdXVCopyPackedData(KdScreenInfo *screen, CARD8 *src, CARD8 *dst, int randr,
1728706f2543Smrg    int srcPitch, int dstPitch, int srcW, int srcH, int top, int left,
1729706f2543Smrg    int h, int w)
1730706f2543Smrg{
1731706f2543Smrg    int srcDown = srcPitch, srcRight = 2, srcNext;
1732706f2543Smrg    int p;
1733706f2543Smrg
1734706f2543Smrg    switch (randr & RR_Rotate_All) {
1735706f2543Smrg    case RR_Rotate_0:
1736706f2543Smrg	srcDown = srcPitch;
1737706f2543Smrg	srcRight = 2;
1738706f2543Smrg	break;
1739706f2543Smrg    case RR_Rotate_90:
1740706f2543Smrg	src += (srcH - 1) * 2;
1741706f2543Smrg	srcDown = -2;
1742706f2543Smrg	srcRight = srcPitch;
1743706f2543Smrg	break;
1744706f2543Smrg    case RR_Rotate_180:
1745706f2543Smrg	src += srcPitch * (srcH - 1) + (srcW - 1) * 2;
1746706f2543Smrg	srcDown = -srcPitch;
1747706f2543Smrg	srcRight = -2;
1748706f2543Smrg	break;
1749706f2543Smrg    case RR_Rotate_270:
1750706f2543Smrg	src += srcPitch * (srcW - 1);
1751706f2543Smrg	srcDown = 2;
1752706f2543Smrg	srcRight = -srcPitch;
1753706f2543Smrg	break;
1754706f2543Smrg    }
1755706f2543Smrg
1756706f2543Smrg    src = src + top * srcDown + left * srcRight;
1757706f2543Smrg
1758706f2543Smrg    w >>= 1;
1759706f2543Smrg    /* srcRight >>= 1; */
1760706f2543Smrg    srcNext = srcRight >> 1;
1761706f2543Smrg    while (h--) {
1762706f2543Smrg	CARD16 *s = (CARD16 *)src;
1763706f2543Smrg	CARD32 *d = (CARD32 *)dst;
1764706f2543Smrg	p = w;
1765706f2543Smrg	while (p--) {
1766706f2543Smrg	    *d++ = s[0] | (s[srcNext] << 16);
1767706f2543Smrg	    s += srcRight;
1768706f2543Smrg	}
1769706f2543Smrg	src += srcPitch;
1770706f2543Smrg	dst += dstPitch;
1771706f2543Smrg    }
1772706f2543Smrg}
1773706f2543Smrg
1774706f2543Smrgvoid
1775706f2543SmrgKdXVCopyPlanarData(KdScreenInfo *screen, CARD8 *src, CARD8 *dst, int randr,
1776706f2543Smrg    int srcPitch, int srcPitch2, int dstPitch, int srcW, int srcH, int height,
1777706f2543Smrg    int top, int left, int h, int w, int id)
1778706f2543Smrg{
1779706f2543Smrg    int i, j;
1780706f2543Smrg    CARD8 *src1, *src2, *src3, *dst1;
1781706f2543Smrg    int srcDown = srcPitch, srcDown2 = srcPitch2;
1782706f2543Smrg    int srcRight = 2, srcRight2 = 1, srcNext = 1;
1783706f2543Smrg
1784706f2543Smrg    /* compute source data pointers */
1785706f2543Smrg    src1 = src;
1786706f2543Smrg    src2 = src1 + height * srcPitch;
1787706f2543Smrg    src3 = src2 + (height >> 1) * srcPitch2;
1788706f2543Smrg    switch (randr & RR_Rotate_All) {
1789706f2543Smrg    case RR_Rotate_0:
1790706f2543Smrg	srcDown = srcPitch;
1791706f2543Smrg	srcDown2 = srcPitch2;
1792706f2543Smrg	srcRight = 2;
1793706f2543Smrg	srcRight2 = 1;
1794706f2543Smrg	srcNext = 1;
1795706f2543Smrg	break;
1796706f2543Smrg    case RR_Rotate_90:
1797706f2543Smrg	src1 = src1 + srcH - 1;
1798706f2543Smrg	src2 = src2 + (srcH >> 1) - 1;
1799706f2543Smrg	src3 = src3 + (srcH >> 1) - 1;
1800706f2543Smrg	srcDown = -1;
1801706f2543Smrg	srcDown2 = -1;
1802706f2543Smrg	srcRight = srcPitch * 2;
1803706f2543Smrg	srcRight2 = srcPitch2;
1804706f2543Smrg	srcNext = srcPitch;
1805706f2543Smrg	break;
1806706f2543Smrg    case RR_Rotate_180:
1807706f2543Smrg	src1 = src1 + srcPitch * (srcH - 1) + (srcW - 1);
1808706f2543Smrg	src2 = src2 + srcPitch2 * ((srcH >> 1) - 1) + ((srcW >> 1) - 1);
1809706f2543Smrg	src3 = src3 + srcPitch2 * ((srcH >> 1) - 1) + ((srcW >> 1) - 1);
1810706f2543Smrg	srcDown = -srcPitch;
1811706f2543Smrg	srcDown2 = -srcPitch2;
1812706f2543Smrg	srcRight = -2;
1813706f2543Smrg	srcRight2 = -1;
1814706f2543Smrg	srcNext = -1;
1815706f2543Smrg	break;
1816706f2543Smrg    case RR_Rotate_270:
1817706f2543Smrg	src1 = src1 + srcPitch * (srcW - 1);
1818706f2543Smrg	src2 = src2 + srcPitch2 * ((srcW >> 1) - 1);
1819706f2543Smrg	src3 = src3 + srcPitch2 * ((srcW >> 1) - 1);
1820706f2543Smrg	srcDown = 1;
1821706f2543Smrg	srcDown2 = 1;
1822706f2543Smrg	srcRight = -srcPitch * 2;
1823706f2543Smrg	srcRight2 = -srcPitch2;
1824706f2543Smrg	srcNext = -srcPitch;
1825706f2543Smrg	break;
1826706f2543Smrg    }
1827706f2543Smrg
1828706f2543Smrg    /* adjust for origin */
1829706f2543Smrg    src1 += top * srcDown + left * srcNext;
1830706f2543Smrg    src2 += (top >> 1) * srcDown2 + (left >> 1) * srcRight2;
1831706f2543Smrg    src3 += (top >> 1) * srcDown2 + (left >> 1) * srcRight2;
1832706f2543Smrg
1833706f2543Smrg    if (id == FOURCC_I420) {
1834706f2543Smrg	CARD8 *srct = src2;
1835706f2543Smrg	src2 = src3;
1836706f2543Smrg	src3 = srct;
1837706f2543Smrg    }
1838706f2543Smrg
1839706f2543Smrg    dst1 = dst;
1840706f2543Smrg
1841706f2543Smrg    w >>= 1;
1842706f2543Smrg    for (j = 0; j < h; j++) {
1843706f2543Smrg	CARD32 *dst = (CARD32 *)dst1;
1844706f2543Smrg	CARD8 *s1l = src1;
1845706f2543Smrg	CARD8 *s1r = src1 + srcNext;
1846706f2543Smrg	CARD8 *s2 = src2;
1847706f2543Smrg	CARD8 *s3 = src3;
1848706f2543Smrg
1849706f2543Smrg	for (i = 0; i < w; i++) {
1850706f2543Smrg	    *dst++ = *s1l | (*s1r << 16) | (*s3 << 8) | (*s2 << 24);
1851706f2543Smrg	    s1l += srcRight;
1852706f2543Smrg	    s1r += srcRight;
1853706f2543Smrg	    s2 += srcRight2;
1854706f2543Smrg	    s3 += srcRight2;
1855706f2543Smrg	}
1856706f2543Smrg	src1 += srcDown;
1857706f2543Smrg	dst1 += dstPitch;
1858706f2543Smrg	if (j & 1) {
1859706f2543Smrg	    src2 += srcDown2;
1860706f2543Smrg	    src3 += srcDown2;
1861706f2543Smrg	}
1862706f2543Smrg    }
1863706f2543Smrg}
1864706f2543Smrg
1865706f2543Smrgvoid
1866706f2543SmrgKXVPaintRegion (DrawablePtr pDraw, RegionPtr pRgn, Pixel fg)
1867706f2543Smrg{
1868706f2543Smrg    GCPtr	pGC;
1869706f2543Smrg    ChangeGCVal	val[2];
1870706f2543Smrg    xRectangle	*rects, *r;
1871706f2543Smrg    BoxPtr	pBox = RegionRects (pRgn);
1872706f2543Smrg    int		nBox = RegionNumRects (pRgn);
1873706f2543Smrg
1874706f2543Smrg    rects = malloc(nBox * sizeof (xRectangle));
1875706f2543Smrg    if (!rects)
1876706f2543Smrg	goto bail0;
1877706f2543Smrg    r = rects;
1878706f2543Smrg    while (nBox--)
1879706f2543Smrg    {
1880706f2543Smrg	r->x = pBox->x1 - pDraw->x;
1881706f2543Smrg	r->y = pBox->y1 - pDraw->y;
1882706f2543Smrg	r->width = pBox->x2 - pBox->x1;
1883706f2543Smrg	r->height = pBox->y2 - pBox->y1;
1884706f2543Smrg	r++;
1885706f2543Smrg	pBox++;
1886706f2543Smrg    }
1887706f2543Smrg
1888706f2543Smrg    pGC = GetScratchGC (pDraw->depth, pDraw->pScreen);
1889706f2543Smrg    if (!pGC)
1890706f2543Smrg	goto bail1;
1891706f2543Smrg
1892706f2543Smrg    val[0].val = fg;
1893706f2543Smrg    val[1].val = IncludeInferiors;
1894706f2543Smrg    ChangeGC (NullClient, pGC, GCForeground|GCSubwindowMode, val);
1895706f2543Smrg
1896706f2543Smrg    ValidateGC (pDraw, pGC);
1897706f2543Smrg
1898706f2543Smrg    (*pGC->ops->PolyFillRect) (pDraw, pGC,
1899706f2543Smrg			       RegionNumRects (pRgn), rects);
1900706f2543Smrg
1901706f2543Smrg    FreeScratchGC (pGC);
1902706f2543Smrgbail1:
1903706f2543Smrg    free(rects);
1904706f2543Smrgbail0:
1905706f2543Smrg    ;
1906706f2543Smrg}
1907