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