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