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