kxv.c revision 4642e01f
1/*
2
3   XFree86 Xv DDX written by Mark Vojkovich (markv@valinux.com)
4   Adapted for KDrive by Pontus Lidman <pontus.lidman@nokia.com>
5
6   Copyright (C) 2000, 2001 - Nokia Home Communications
7   Copyright (C) 1998, 1999 - The XFree86 Project Inc.
8
9All rights reserved.
10
11Permission is hereby granted, free of charge, to any person obtaining
12a copy of this software and associated documentation files (the
13"Software"), to deal in the Software without restriction, including
14without limitation the rights to use, copy, modify, merge, publish,
15distribute, and/or sell copies of the Software, and to permit persons
16to whom the Software is furnished to do so, provided that the above
17copyright notice(s) and this permission notice appear in all copies of
18the Software and that both the above copyright notice(s) and this
19permission notice appear in supporting documentation.
20
21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
24OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
25HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
26SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
27RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
28CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
29CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
30
31Except as contained in this notice, the name of a copyright holder
32shall not be used in advertising or otherwise to promote the sale, use
33or other dealings in this Software without prior written authorization
34of the copyright holder.
35
36*/
37
38#ifdef HAVE_CONFIG_H
39#include <kdrive-config.h>
40#endif
41#include "kdrive.h"
42
43#include "scrnintstr.h"
44#include "regionstr.h"
45#include "windowstr.h"
46#include "pixmapstr.h"
47#include "mivalidate.h"
48#include "validate.h"
49#include "resource.h"
50#include "gcstruct.h"
51#include "dixstruct.h"
52
53#include <X11/extensions/Xv.h>
54#include <X11/extensions/Xvproto.h>
55
56#include "kxv.h"
57#include "fourcc.h"
58
59
60/* XvScreenRec fields */
61
62static Bool KdXVCloseScreen(int, ScreenPtr);
63static int KdXVQueryAdaptors(ScreenPtr, XvAdaptorPtr *, int *);
64
65/* XvAdaptorRec fields */
66
67static int KdXVAllocatePort(unsigned long, XvPortPtr, XvPortPtr*);
68static int KdXVFreePort(XvPortPtr);
69static int KdXVPutVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr,
70   				INT16, INT16, CARD16, CARD16,
71				INT16, INT16, CARD16, CARD16);
72static int KdXVPutStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr,
73   				INT16, INT16, CARD16, CARD16,
74				INT16, INT16, CARD16, CARD16);
75static int KdXVGetVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr,
76   				INT16, INT16, CARD16, CARD16,
77				INT16, INT16, CARD16, CARD16);
78static int KdXVGetStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr,
79   				INT16, INT16, CARD16, CARD16,
80				INT16, INT16, CARD16, CARD16);
81static int KdXVStopVideo(ClientPtr, XvPortPtr, DrawablePtr);
82static int KdXVSetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32);
83static int KdXVGetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32 *);
84static int KdXVQueryBestSize(ClientPtr, XvPortPtr, CARD8,
85   				CARD16, CARD16,CARD16, CARD16,
86				unsigned int*, unsigned int*);
87static int KdXVPutImage(ClientPtr, DrawablePtr, XvPortPtr, GCPtr,
88   				INT16, INT16, CARD16, CARD16,
89				INT16, INT16, CARD16, CARD16,
90				XvImagePtr, unsigned char*, Bool,
91				CARD16, CARD16);
92static int KdXVQueryImageAttributes(ClientPtr, XvPortPtr, XvImagePtr,
93				CARD16*, CARD16*, int*, int*);
94
95
96/* ScreenRec fields */
97
98static Bool KdXVCreateWindow(WindowPtr pWin);
99static Bool KdXVDestroyWindow(WindowPtr pWin);
100static void KdXVWindowExposures(WindowPtr pWin, RegionPtr r1, RegionPtr r2);
101static void KdXVClipNotify(WindowPtr pWin, int dx, int dy);
102
103/* misc */
104static Bool KdXVInitAdaptors(ScreenPtr, KdVideoAdaptorPtr*, int);
105
106static int KdXVWindowKeyIndex;
107DevPrivateKey KdXVWindowKey = &KdXVWindowKeyIndex;
108static int KdXvScreenKeyIndex;
109DevPrivateKey KdXvScreenKey = &KdXvScreenKeyIndex;
110static unsigned long KdXVGeneration = 0;
111static unsigned long PortResource = 0;
112
113DevPrivateKey (*XvGetScreenKeyProc)(void) = XvGetScreenKey;
114unsigned long (*XvGetRTPortProc)(void) = XvGetRTPort;
115int (*XvScreenInitProc)(ScreenPtr) = XvScreenInit;
116
117#define GET_XV_SCREEN(pScreen) ((XvScreenPtr) \
118    dixLookupPrivate(&(pScreen)->devPrivates, KdXvScreenKey))
119
120#define GET_KDXV_SCREEN(pScreen) \
121  	((KdXVScreenPtr)(GET_XV_SCREEN(pScreen)->devPriv.ptr))
122
123#define GET_KDXV_WINDOW(pWin) ((KdXVWindowPtr) \
124    dixLookupPrivate(&(pWin)->devPrivates, KdXVWindowKey))
125
126static KdXVInitGenericAdaptorPtr *GenDrivers = NULL;
127static int NumGenDrivers = 0;
128
129int
130KdXVRegisterGenericAdaptorDriver(
131    KdXVInitGenericAdaptorPtr InitFunc
132){
133  KdXVInitGenericAdaptorPtr *newdrivers;
134
135/*   fprintf(stderr,"KdXVRegisterGenericAdaptorDriver\n"); */
136
137  newdrivers = xrealloc(GenDrivers, sizeof(KdXVInitGenericAdaptorPtr) *
138			(1 + NumGenDrivers));
139  if (!newdrivers)
140    return 0;
141  GenDrivers = newdrivers;
142
143  GenDrivers[NumGenDrivers++] = InitFunc;
144
145  return 1;
146}
147
148int
149KdXVListGenericAdaptors(
150    KdScreenInfo *          screen,
151    KdVideoAdaptorPtr **adaptors
152){
153    int i,j,n,num;
154    KdVideoAdaptorPtr *DrivAdap,*new;
155
156    num = 0;
157    *adaptors = NULL;
158    for (i = 0; i < NumGenDrivers; i++) {
159	n = GenDrivers[i](screen,&DrivAdap);
160	if (0 == n)
161	    continue;
162	new = xrealloc(*adaptors, sizeof(KdVideoAdaptorPtr) * (num+n));
163	if (NULL == new)
164	    continue;
165	*adaptors = new;
166	for (j = 0; j < n; j++, num++)
167	    (*adaptors)[num] = DrivAdap[j];
168    }
169    return num;
170}
171
172KdVideoAdaptorPtr
173KdXVAllocateVideoAdaptorRec(KdScreenInfo * screen)
174{
175    return xcalloc(1, sizeof(KdVideoAdaptorRec));
176}
177
178void
179KdXVFreeVideoAdaptorRec(KdVideoAdaptorPtr ptr)
180{
181    xfree(ptr);
182}
183
184
185Bool
186KdXVScreenInit(
187   ScreenPtr pScreen,
188   KdVideoAdaptorPtr *adaptors,
189   int num
190){
191  KdXVScreenPtr ScreenPriv;
192  XvScreenPtr pxvs;
193
194/*   fprintf(stderr,"KdXVScreenInit initializing %d adaptors\n",num); */
195
196  if (KdXVGeneration != serverGeneration)
197      KdXVGeneration = serverGeneration;
198
199  if(!XvGetScreenKeyProc || !XvGetRTPortProc || !XvScreenInitProc)
200	return FALSE;
201
202  if(Success != (*XvScreenInitProc)(pScreen)) return FALSE;
203
204  KdXvScreenKey = (*XvGetScreenKeyProc)();
205  PortResource = (*XvGetRTPortProc)();
206
207  pxvs = GET_XV_SCREEN(pScreen);
208
209
210  /* Anyone initializing the Xv layer must provide these two.
211     The Xv di layer calls them without even checking if they exist! */
212
213  pxvs->ddCloseScreen = KdXVCloseScreen;
214  pxvs->ddQueryAdaptors = KdXVQueryAdaptors;
215
216  /* The Xv di layer provides us with a private hook so that we don't
217     have to allocate our own screen private.  They also provide
218     a CloseScreen hook so that we don't have to wrap it.  I'm not
219     sure that I appreciate that.  */
220
221  ScreenPriv = xalloc(sizeof(KdXVScreenRec));
222  pxvs->devPriv.ptr = (pointer)ScreenPriv;
223
224  if(!ScreenPriv) return FALSE;
225
226
227  ScreenPriv->CreateWindow = pScreen->CreateWindow;
228  ScreenPriv->DestroyWindow = pScreen->DestroyWindow;
229  ScreenPriv->WindowExposures = pScreen->WindowExposures;
230  ScreenPriv->ClipNotify = pScreen->ClipNotify;
231
232/*   fprintf(stderr,"XV: Wrapping screen funcs\n"); */
233
234  pScreen->CreateWindow = KdXVCreateWindow;
235  pScreen->DestroyWindow = KdXVDestroyWindow;
236  pScreen->WindowExposures = KdXVWindowExposures;
237  pScreen->ClipNotify = KdXVClipNotify;
238
239  if(!KdXVInitAdaptors(pScreen, adaptors, num))
240	return FALSE;
241
242  return TRUE;
243}
244
245static void
246KdXVFreeAdaptor(XvAdaptorPtr pAdaptor)
247{
248   int i;
249
250   if(pAdaptor->name)
251      xfree(pAdaptor->name);
252
253   if(pAdaptor->pEncodings) {
254      XvEncodingPtr pEncode = pAdaptor->pEncodings;
255
256      for(i = 0; i < pAdaptor->nEncodings; i++, pEncode++) {
257          if(pEncode->name) xfree(pEncode->name);
258      }
259      xfree(pAdaptor->pEncodings);
260   }
261
262   if(pAdaptor->pFormats)
263      xfree(pAdaptor->pFormats);
264
265   if(pAdaptor->pPorts) {
266      XvPortPtr pPort = pAdaptor->pPorts;
267      XvPortRecPrivatePtr pPriv;
268
269      for(i = 0; i < pAdaptor->nPorts; i++, pPort++) {
270          pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr;
271	  if(pPriv) {
272	     if(pPriv->clientClip)
273		REGION_DESTROY(pAdaptor->pScreen, pPriv->clientClip);
274             if(pPriv->pCompositeClip && pPriv->FreeCompositeClip)
275		REGION_DESTROY(pAdaptor->pScreen, pPriv->pCompositeClip);
276	     xfree(pPriv);
277	  }
278      }
279      xfree(pAdaptor->pPorts);
280   }
281
282   if(pAdaptor->nAttributes) {
283      XvAttributePtr pAttribute = pAdaptor->pAttributes;
284
285      for(i = 0; i < pAdaptor->nAttributes; i++, pAttribute++) {
286          if(pAttribute->name) xfree(pAttribute->name);
287      }
288
289      xfree(pAdaptor->pAttributes);
290   }
291
292   if(pAdaptor->nImages)
293      xfree(pAdaptor->pImages);
294
295   if(pAdaptor->devPriv.ptr)
296      xfree(pAdaptor->devPriv.ptr);
297}
298
299static Bool
300KdXVInitAdaptors(
301   ScreenPtr pScreen,
302   KdVideoAdaptorPtr *infoPtr,
303   int number
304) {
305    KdScreenPriv(pScreen);
306    KdScreenInfo * screen = pScreenPriv->screen;
307
308  XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
309  KdVideoAdaptorPtr adaptorPtr;
310  XvAdaptorPtr pAdaptor, pa;
311  XvAdaptorRecPrivatePtr adaptorPriv;
312  int na, numAdaptor;
313  XvPortRecPrivatePtr portPriv;
314  XvPortPtr pPort, pp;
315  int numPort;
316  KdAttributePtr attributePtr;
317  XvAttributePtr pAttribute, pat;
318  KdVideoFormatPtr formatPtr;
319  XvFormatPtr pFormat, pf;
320  int numFormat, totFormat;
321  KdVideoEncodingPtr encodingPtr;
322  XvEncodingPtr pEncode, pe;
323  KdImagePtr imagePtr;
324  XvImagePtr pImage, pi;
325  int numVisuals;
326  VisualPtr pVisual;
327  int i;
328
329  pxvs->nAdaptors = 0;
330  pxvs->pAdaptors = NULL;
331
332  if(!(pAdaptor = xcalloc(number, sizeof(XvAdaptorRec))))
333      return FALSE;
334
335  for(pa = pAdaptor, na = 0, numAdaptor = 0; na < number; na++, adaptorPtr++) {
336      adaptorPtr = infoPtr[na];
337
338      if(!adaptorPtr->StopVideo || !adaptorPtr->SetPortAttribute ||
339	 !adaptorPtr->GetPortAttribute || !adaptorPtr->QueryBestSize)
340	   continue;
341
342      /* client libs expect at least one encoding */
343      if(!adaptorPtr->nEncodings || !adaptorPtr->pEncodings)
344	   continue;
345
346      pa->type = adaptorPtr->type;
347
348      if(!adaptorPtr->PutVideo && !adaptorPtr->GetVideo)
349	 pa->type &= ~XvVideoMask;
350
351      if(!adaptorPtr->PutStill && !adaptorPtr->GetStill)
352	 pa->type &= ~XvStillMask;
353
354      if(!adaptorPtr->PutImage || !adaptorPtr->QueryImageAttributes)
355	 pa->type &= ~XvImageMask;
356
357      if(!adaptorPtr->PutVideo && !adaptorPtr->PutImage &&
358							  !adaptorPtr->PutStill)
359	 pa->type &= ~XvInputMask;
360
361      if(!adaptorPtr->GetVideo && !adaptorPtr->GetStill)
362	 pa->type &= ~XvOutputMask;
363
364      if(!(adaptorPtr->type & (XvPixmapMask | XvWindowMask)))
365	  continue;
366      if(!(adaptorPtr->type & (XvImageMask | XvVideoMask | XvStillMask)))
367	  continue;
368
369      pa->pScreen = pScreen;
370      pa->ddAllocatePort = KdXVAllocatePort;
371      pa->ddFreePort = KdXVFreePort;
372      pa->ddPutVideo = KdXVPutVideo;
373      pa->ddPutStill = KdXVPutStill;
374      pa->ddGetVideo = KdXVGetVideo;
375      pa->ddGetStill = KdXVGetStill;
376      pa->ddStopVideo = KdXVStopVideo;
377      pa->ddPutImage = KdXVPutImage;
378      pa->ddSetPortAttribute = KdXVSetPortAttribute;
379      pa->ddGetPortAttribute = KdXVGetPortAttribute;
380      pa->ddQueryBestSize = KdXVQueryBestSize;
381      pa->ddQueryImageAttributes = KdXVQueryImageAttributes;
382      if((pa->name = xalloc(strlen(adaptorPtr->name) + 1)))
383          strcpy(pa->name, adaptorPtr->name);
384
385      if(adaptorPtr->nEncodings &&
386	(pEncode = xcalloc(adaptorPtr->nEncodings, sizeof(XvEncodingRec)))) {
387
388	for(pe = pEncode, encodingPtr = adaptorPtr->pEncodings, i = 0;
389	    i < adaptorPtr->nEncodings; pe++, i++, encodingPtr++)
390        {
391	    pe->id = encodingPtr->id;
392	    pe->pScreen = pScreen;
393	    if((pe->name = xalloc(strlen(encodingPtr->name) + 1)))
394                strcpy(pe->name, encodingPtr->name);
395	    pe->width = encodingPtr->width;
396	    pe->height = encodingPtr->height;
397	    pe->rate.numerator = encodingPtr->rate.numerator;
398	    pe->rate.denominator = encodingPtr->rate.denominator;
399	}
400	pa->nEncodings = adaptorPtr->nEncodings;
401	pa->pEncodings = pEncode;
402      }
403
404      if(adaptorPtr->nImages &&
405         (pImage = xcalloc(adaptorPtr->nImages, sizeof(XvImageRec)))) {
406
407          for(i = 0, pi = pImage, imagePtr = adaptorPtr->pImages;
408	      i < adaptorPtr->nImages; i++, pi++, imagePtr++)
409  	  {
410	     pi->id = imagePtr->id;
411	     pi->type = imagePtr->type;
412	     pi->byte_order = imagePtr->byte_order;
413	     memcpy(pi->guid, imagePtr->guid, 16);
414	     pi->bits_per_pixel = imagePtr->bits_per_pixel;
415	     pi->format = imagePtr->format;
416	     pi->num_planes = imagePtr->num_planes;
417	     pi->depth = imagePtr->depth;
418	     pi->red_mask = imagePtr->red_mask;
419	     pi->green_mask = imagePtr->green_mask;
420	     pi->blue_mask = imagePtr->blue_mask;
421	     pi->y_sample_bits = imagePtr->y_sample_bits;
422	     pi->u_sample_bits = imagePtr->u_sample_bits;
423	     pi->v_sample_bits = imagePtr->v_sample_bits;
424	     pi->horz_y_period = imagePtr->horz_y_period;
425	     pi->horz_u_period = imagePtr->horz_u_period;
426	     pi->horz_v_period = imagePtr->horz_v_period;
427	     pi->vert_y_period = imagePtr->vert_y_period;
428	     pi->vert_u_period = imagePtr->vert_u_period;
429	     pi->vert_v_period = imagePtr->vert_v_period;
430	     memcpy(pi->component_order, imagePtr->component_order, 32);
431	     pi->scanline_order = imagePtr->scanline_order;
432          }
433	  pa->nImages = adaptorPtr->nImages;
434	  pa->pImages = pImage;
435      }
436
437      if(adaptorPtr->nAttributes &&
438	(pAttribute = xcalloc(adaptorPtr->nAttributes, sizeof(XvAttributeRec))))
439      {
440	for(pat = pAttribute, attributePtr = adaptorPtr->pAttributes, i = 0;
441	    i < adaptorPtr->nAttributes; pat++, i++, attributePtr++)
442        {
443	    pat->flags = attributePtr->flags;
444	    pat->min_value = attributePtr->min_value;
445	    pat->max_value = attributePtr->max_value;
446	    if((pat->name = xalloc(strlen(attributePtr->name) + 1)))
447                strcpy(pat->name, attributePtr->name);
448	}
449	pa->nAttributes = adaptorPtr->nAttributes;
450	pa->pAttributes = pAttribute;
451      }
452
453
454      totFormat = adaptorPtr->nFormats;
455
456      if(!(pFormat = xcalloc(totFormat, sizeof(XvFormatRec)))) {
457          KdXVFreeAdaptor(pa);
458          continue;
459      }
460      for(pf = pFormat, i = 0, numFormat = 0, formatPtr = adaptorPtr->pFormats;
461	  i < adaptorPtr->nFormats; i++, formatPtr++)
462      {
463	  numVisuals = pScreen->numVisuals;
464          pVisual = pScreen->visuals;
465
466          while(numVisuals--) {
467              if((pVisual->class == formatPtr->class) &&
468                 (pVisual->nplanes == formatPtr->depth)) {
469
470		   if(numFormat >= totFormat) {
471			void *moreSpace;
472			totFormat *= 2;
473			moreSpace = xrealloc(pFormat,
474					     totFormat * sizeof(XvFormatRec));
475			if(!moreSpace) break;
476			pFormat = moreSpace;
477			pf = pFormat + numFormat;
478		   }
479
480                   pf->visual = pVisual->vid;
481		   pf->depth = formatPtr->depth;
482
483		   pf++;
484		   numFormat++;
485              }
486              pVisual++;
487          }
488      }
489      pa->nFormats = numFormat;
490      pa->pFormats = pFormat;
491      if(!numFormat) {
492          KdXVFreeAdaptor(pa);
493          continue;
494      }
495
496      if(!(adaptorPriv = xcalloc(1, sizeof(XvAdaptorRecPrivate)))) {
497          KdXVFreeAdaptor(pa);
498          continue;
499      }
500
501      adaptorPriv->flags = adaptorPtr->flags;
502      adaptorPriv->PutVideo = adaptorPtr->PutVideo;
503      adaptorPriv->PutStill = adaptorPtr->PutStill;
504      adaptorPriv->GetVideo = adaptorPtr->GetVideo;
505      adaptorPriv->GetStill = adaptorPtr->GetStill;
506      adaptorPriv->StopVideo = adaptorPtr->StopVideo;
507      adaptorPriv->SetPortAttribute = adaptorPtr->SetPortAttribute;
508      adaptorPriv->GetPortAttribute = adaptorPtr->GetPortAttribute;
509      adaptorPriv->QueryBestSize = adaptorPtr->QueryBestSize;
510      adaptorPriv->QueryImageAttributes = adaptorPtr->QueryImageAttributes;
511      adaptorPriv->PutImage = adaptorPtr->PutImage;
512      adaptorPriv->ReputImage = adaptorPtr->ReputImage;
513
514      pa->devPriv.ptr = (pointer)adaptorPriv;
515
516      if(!(pPort = xcalloc(adaptorPtr->nPorts, sizeof(XvPortRec)))) {
517          KdXVFreeAdaptor(pa);
518          continue;
519      }
520      for(pp = pPort, i = 0, numPort = 0;
521	  i < adaptorPtr->nPorts; i++) {
522
523          if(!(pp->id = FakeClientID(0)))
524		continue;
525
526	  if(!(portPriv = xcalloc(1, sizeof(XvPortRecPrivate))))
527		continue;
528
529	  if(!AddResource(pp->id, PortResource, pp)) {
530		xfree(portPriv);
531		continue;
532	  }
533
534          pp->pAdaptor = pa;
535          pp->pNotify = (XvPortNotifyPtr)NULL;
536          pp->pDraw = (DrawablePtr)NULL;
537          pp->client = (ClientPtr)NULL;
538          pp->grab.client = (ClientPtr)NULL;
539          pp->time = currentTime;
540          pp->devPriv.ptr = portPriv;
541
542	  portPriv->screen = screen;
543	  portPriv->AdaptorRec = adaptorPriv;
544          portPriv->DevPriv.ptr = adaptorPtr->pPortPrivates[i].ptr;
545
546          pp++;
547          numPort++;
548      }
549      pa->nPorts = numPort;
550      pa->pPorts = pPort;
551      if(!numPort) {
552          KdXVFreeAdaptor(pa);
553          continue;
554      }
555
556      pa->base_id = pPort->id;
557
558      pa++;
559      numAdaptor++;
560  }
561
562  if(numAdaptor) {
563      pxvs->nAdaptors = numAdaptor;
564      pxvs->pAdaptors = pAdaptor;
565  } else {
566     xfree(pAdaptor);
567     return FALSE;
568  }
569
570  return TRUE;
571}
572
573/* Video should be clipped to the intersection of the window cliplist
574   and the client cliplist specified in the GC for which the video was
575   initialized.  When we need to reclip a window, the GC that started
576   the video may not even be around anymore.  That's why we save the
577   client clip from the GC when the video is initialized.  We then
578   use KdXVUpdateCompositeClip to calculate the new composite clip
579   when we need it.  This is different from what DEC did.  They saved
580   the GC and used it's clip list when they needed to reclip the window,
581   even if the client clip was different from the one the video was
582   initialized with.  If the original GC was destroyed, they had to stop
583   the video.  I like the new method better (MArk).
584
585   This function only works for windows.  Will need to rewrite when
586   (if) we support pixmap rendering.
587*/
588
589static void
590KdXVUpdateCompositeClip(XvPortRecPrivatePtr portPriv)
591{
592   RegionPtr	pregWin, pCompositeClip;
593   WindowPtr	pWin;
594   Bool 	freeCompClip = FALSE;
595
596   if(portPriv->pCompositeClip)
597	return;
598
599   pWin = (WindowPtr)portPriv->pDraw;
600
601   /* get window clip list */
602   if(portPriv->subWindowMode == IncludeInferiors) {
603	pregWin = NotClippedByChildren(pWin);
604	freeCompClip = TRUE;
605   } else
606	pregWin = &pWin->clipList;
607
608   if(!portPriv->clientClip) {
609	portPriv->pCompositeClip = pregWin;
610	portPriv->FreeCompositeClip = freeCompClip;
611	return;
612   }
613
614   pCompositeClip = REGION_CREATE(pWin->pScreen, NullBox, 1);
615   REGION_COPY(pWin->pScreen, pCompositeClip, portPriv->clientClip);
616   REGION_TRANSLATE(pWin->pScreen, pCompositeClip,
617			portPriv->pDraw->x + portPriv->clipOrg.x,
618			portPriv->pDraw->y + portPriv->clipOrg.y);
619   REGION_INTERSECT(pWin->pScreen, pCompositeClip, pregWin, pCompositeClip);
620
621   portPriv->pCompositeClip = pCompositeClip;
622   portPriv->FreeCompositeClip = TRUE;
623
624   if(freeCompClip) {
625   	REGION_DESTROY(pWin->pScreen, pregWin);
626   }
627}
628
629/* Save the current clientClip and update the CompositeClip whenever
630   we have a fresh GC */
631
632static void
633KdXVCopyClip(
634   XvPortRecPrivatePtr portPriv,
635   GCPtr pGC
636){
637    /* copy the new clip if it exists */
638    if((pGC->clientClipType == CT_REGION) && pGC->clientClip) {
639	if(!portPriv->clientClip)
640	    portPriv->clientClip = REGION_CREATE(pGC->pScreen, NullBox, 1);
641	/* Note: this is in window coordinates */
642	REGION_COPY(pGC->pScreen, portPriv->clientClip, pGC->clientClip);
643    } else if(portPriv->clientClip) { /* free the old clientClip */
644	REGION_DESTROY(pGC->pScreen, portPriv->clientClip);
645	portPriv->clientClip = NULL;
646    }
647
648    /* get rid of the old clip list */
649    if(portPriv->pCompositeClip && portPriv->FreeCompositeClip) {
650	REGION_DESTROY(pWin->pScreen, portPriv->pCompositeClip);
651    }
652
653    portPriv->clipOrg = pGC->clipOrg;
654    portPriv->pCompositeClip = pGC->pCompositeClip;
655    portPriv->FreeCompositeClip = FALSE;
656    portPriv->subWindowMode = pGC->subWindowMode;
657}
658
659static int
660KdXVRegetVideo(XvPortRecPrivatePtr portPriv)
661{
662  RegionRec WinRegion;
663  RegionRec ClipRegion;
664  BoxRec WinBox;
665  int ret = Success;
666  Bool clippedAway = FALSE;
667
668  KdXVUpdateCompositeClip(portPriv);
669
670  /* translate the video region to the screen */
671  WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
672  WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
673  WinBox.x2 = WinBox.x1 + portPriv->drw_w;
674  WinBox.y2 = WinBox.y1 + portPriv->drw_h;
675
676  /* clip to the window composite clip */
677  REGION_INIT(portPriv->pDraw->pScreen, &WinRegion, &WinBox, 1);
678  REGION_INIT(portPriv->pDraw->pScreen, &ClipRegion, NullBox, 1);
679  REGION_INTERSECT(portPriv->pDraw->pScreen, &ClipRegion, &WinRegion, portPriv->pCompositeClip);
680
681  /* that's all if it's totally obscured */
682  if(!REGION_NOTEMPTY(portPriv->pDraw->pScreen, &ClipRegion)) {
683	clippedAway = TRUE;
684	goto CLIP_VIDEO_BAILOUT;
685  }
686
687  if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
688     REGION_SUBTRACT(portPriv->pDraw->pScreen, &ClipRegion, &WinRegion, &ClipRegion);
689  }
690
691  ret = (*portPriv->AdaptorRec->GetVideo)(portPriv->screen, portPriv->pDraw,
692			portPriv->vid_x, portPriv->vid_y,
693			WinBox.x1, WinBox.y1,
694			portPriv->vid_w, portPriv->vid_h,
695			portPriv->drw_w, portPriv->drw_h,
696			&ClipRegion, portPriv->DevPriv.ptr);
697
698  if(ret == Success)
699	portPriv->isOn = XV_ON;
700
701CLIP_VIDEO_BAILOUT:
702
703  if((clippedAway || (ret != Success)) && portPriv->isOn == XV_ON) {
704	(*portPriv->AdaptorRec->StopVideo)(
705		portPriv->screen, portPriv->DevPriv.ptr, FALSE);
706	portPriv->isOn = XV_PENDING;
707  }
708
709  /* This clip was copied and only good for one shot */
710  if(!portPriv->FreeCompositeClip)
711     portPriv->pCompositeClip = NULL;
712
713  REGION_UNINIT(portPriv->pDraw->pScreen, &WinRegion);
714  REGION_UNINIT(portPriv->pDraw->pScreen, &ClipRegion);
715
716  return ret;
717}
718
719
720static int
721KdXVReputVideo(XvPortRecPrivatePtr portPriv)
722{
723  RegionRec WinRegion;
724  RegionRec ClipRegion;
725  BoxRec WinBox;
726  ScreenPtr pScreen = portPriv->pDraw->pScreen;
727  KdScreenPriv(pScreen);
728  KdScreenInfo *screen=pScreenPriv->screen;
729  int ret = Success;
730  Bool clippedAway = FALSE;
731
732  KdXVUpdateCompositeClip(portPriv);
733
734  /* translate the video region to the screen */
735  WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
736  WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
737  WinBox.x2 = WinBox.x1 + portPriv->drw_w;
738  WinBox.y2 = WinBox.y1 + portPriv->drw_h;
739
740  /* clip to the window composite clip */
741  REGION_INIT(pScreen, &WinRegion, &WinBox, 1);
742  REGION_INIT(pScreen, &ClipRegion, NullBox, 1);
743  REGION_INTERSECT(Screen, &ClipRegion, &WinRegion, portPriv->pCompositeClip);
744
745  /* clip and translate to the viewport */
746  if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
747     RegionRec VPReg;
748     BoxRec VPBox;
749
750     VPBox.x1 = 0;
751     VPBox.y1 = 0;
752     VPBox.x2 = screen->width;
753     VPBox.y2 = screen->height;
754
755     REGION_INIT(pScreen, &VPReg, &VPBox, 1);
756     REGION_INTERSECT(Screen, &ClipRegion, &ClipRegion, &VPReg);
757     REGION_UNINIT(pScreen, &VPReg);
758  }
759
760  /* that's all if it's totally obscured */
761  if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) {
762	clippedAway = TRUE;
763	goto CLIP_VIDEO_BAILOUT;
764  }
765
766  /* bailout if we have to clip but the hardware doesn't support it */
767  if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
768     BoxPtr clipBox = REGION_RECTS(&ClipRegion);
769     if(  (REGION_NUM_RECTS(&ClipRegion) != 1) ||
770	  (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
771	  (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2))
772     {
773	    clippedAway = TRUE;
774	    goto CLIP_VIDEO_BAILOUT;
775     }
776  }
777
778  if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
779     REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion);
780  }
781
782  ret = (*portPriv->AdaptorRec->PutVideo)(portPriv->screen, portPriv->pDraw,
783			portPriv->vid_x, portPriv->vid_y,
784			WinBox.x1, WinBox.y1,
785			portPriv->vid_w, portPriv->vid_h,
786			portPriv->drw_w, portPriv->drw_h,
787			&ClipRegion, portPriv->DevPriv.ptr);
788
789  if(ret == Success) portPriv->isOn = XV_ON;
790
791CLIP_VIDEO_BAILOUT:
792
793  if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
794	(*portPriv->AdaptorRec->StopVideo)(
795		portPriv->screen, portPriv->DevPriv.ptr, FALSE);
796	portPriv->isOn = XV_PENDING;
797  }
798
799  /* This clip was copied and only good for one shot */
800  if(!portPriv->FreeCompositeClip)
801     portPriv->pCompositeClip = NULL;
802
803  REGION_UNINIT(pScreen, &WinRegion);
804  REGION_UNINIT(pScreen, &ClipRegion);
805
806  return ret;
807}
808
809static int
810KdXVReputImage(XvPortRecPrivatePtr portPriv)
811{
812  RegionRec WinRegion;
813  RegionRec ClipRegion;
814  BoxRec WinBox;
815  ScreenPtr pScreen = portPriv->pDraw->pScreen;
816  KdScreenPriv(pScreen);
817  KdScreenInfo *screen=pScreenPriv->screen;
818  int ret = Success;
819  Bool clippedAway = FALSE;
820
821  KdXVUpdateCompositeClip(portPriv);
822
823  /* translate the video region to the screen */
824  WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
825  WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
826  WinBox.x2 = WinBox.x1 + portPriv->drw_w;
827  WinBox.y2 = WinBox.y1 + portPriv->drw_h;
828
829  /* clip to the window composite clip */
830  REGION_INIT(pScreen, &WinRegion, &WinBox, 1);
831  REGION_INIT(pScreen, &ClipRegion, NullBox, 1);
832  REGION_INTERSECT(Screen, &ClipRegion, &WinRegion, portPriv->pCompositeClip);
833
834  /* clip and translate to the viewport */
835  if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
836     RegionRec VPReg;
837     BoxRec VPBox;
838
839     VPBox.x1 = 0;
840     VPBox.y1 = 0;
841     VPBox.x2 = screen->width;
842     VPBox.y2 = screen->height;
843
844     REGION_INIT(pScreen, &VPReg, &VPBox, 1);
845     REGION_INTERSECT(Screen, &ClipRegion, &ClipRegion, &VPReg);
846     REGION_UNINIT(pScreen, &VPReg);
847  }
848
849  /* that's all if it's totally obscured */
850  if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) {
851	clippedAway = TRUE;
852	goto CLIP_VIDEO_BAILOUT;
853  }
854
855  /* bailout if we have to clip but the hardware doesn't support it */
856  if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
857     BoxPtr clipBox = REGION_RECTS(&ClipRegion);
858     if(  (REGION_NUM_RECTS(&ClipRegion) != 1) ||
859	  (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
860	  (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2))
861     {
862	    clippedAway = TRUE;
863	    goto CLIP_VIDEO_BAILOUT;
864     }
865  }
866
867  if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
868     REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion);
869  }
870
871  ret = (*portPriv->AdaptorRec->ReputImage)(portPriv->screen, portPriv->pDraw,
872			WinBox.x1, WinBox.y1,
873			&ClipRegion, portPriv->DevPriv.ptr);
874
875  portPriv->isOn = (ret == Success) ? XV_ON : XV_OFF;
876
877CLIP_VIDEO_BAILOUT:
878
879  if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
880	(*portPriv->AdaptorRec->StopVideo)(
881		portPriv->screen, portPriv->DevPriv.ptr, FALSE);
882	portPriv->isOn = XV_PENDING;
883  }
884
885  /* This clip was copied and only good for one shot */
886  if(!portPriv->FreeCompositeClip)
887     portPriv->pCompositeClip = NULL;
888
889  REGION_UNINIT(pScreen, &WinRegion);
890  REGION_UNINIT(pScreen, &ClipRegion);
891
892  return ret;
893}
894
895
896static int
897KdXVReputAllVideo(WindowPtr pWin, pointer data)
898{
899    KdXVWindowPtr WinPriv;
900
901    if (pWin->drawable.type != DRAWABLE_WINDOW)
902	return WT_DONTWALKCHILDREN;
903
904    WinPriv = GET_KDXV_WINDOW(pWin);
905
906    while(WinPriv) {
907	if(WinPriv->PortRec->type == XvInputMask)
908	    KdXVReputVideo(WinPriv->PortRec);
909	else
910	    KdXVRegetVideo(WinPriv->PortRec);
911	WinPriv = WinPriv->next;
912    }
913
914    return WT_WALKCHILDREN;
915}
916
917static int
918KdXVEnlistPortInWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
919{
920   KdXVWindowPtr winPriv, PrivRoot;
921
922   winPriv = PrivRoot = GET_KDXV_WINDOW(pWin);
923
924  /* Enlist our port in the window private */
925   while(winPriv) {
926	if(winPriv->PortRec == portPriv) /* we're already listed */
927	    break;
928	winPriv = winPriv->next;
929   }
930
931   if(!winPriv) {
932	winPriv = xalloc(sizeof(KdXVWindowRec));
933	if(!winPriv) return BadAlloc;
934	winPriv->PortRec = portPriv;
935	winPriv->next = PrivRoot;
936	dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, winPriv);
937   }
938   return Success;
939}
940
941
942static void
943KdXVRemovePortFromWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
944{
945     KdXVWindowPtr winPriv, prevPriv = NULL;
946
947     winPriv = GET_KDXV_WINDOW(pWin);
948
949     while(winPriv) {
950	if(winPriv->PortRec == portPriv) {
951	    if(prevPriv)
952		prevPriv->next = winPriv->next;
953	    else
954		dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, winPriv->next);
955	    xfree(winPriv);
956	    break;
957	}
958	prevPriv = winPriv;
959	winPriv = winPriv->next;
960     }
961     portPriv->pDraw = NULL;
962}
963
964/****  ScreenRec fields ****/
965
966
967static Bool
968KdXVCreateWindow(WindowPtr pWin)
969{
970  ScreenPtr pScreen = pWin->drawable.pScreen;
971  KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
972  int ret;
973
974  pScreen->CreateWindow = ScreenPriv->CreateWindow;
975  ret = (*pScreen->CreateWindow)(pWin);
976  pScreen->CreateWindow = KdXVCreateWindow;
977
978  if (ret)
979      dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, NULL);
980
981  return ret;
982}
983
984
985static Bool
986KdXVDestroyWindow(WindowPtr pWin)
987{
988  ScreenPtr pScreen = pWin->drawable.pScreen;
989  KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
990  KdXVWindowPtr tmp, WinPriv = GET_KDXV_WINDOW(pWin);
991  int ret;
992
993  while(WinPriv) {
994     XvPortRecPrivatePtr pPriv = WinPriv->PortRec;
995
996     if(pPriv->isOn > XV_OFF) {
997	(*pPriv->AdaptorRec->StopVideo)(
998			pPriv->screen, pPriv->DevPriv.ptr, TRUE);
999	pPriv->isOn = XV_OFF;
1000     }
1001
1002     pPriv->pDraw = NULL;
1003     tmp = WinPriv;
1004     WinPriv = WinPriv->next;
1005     xfree(tmp);
1006  }
1007
1008  dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, NULL);
1009
1010  pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
1011  ret = (*pScreen->DestroyWindow)(pWin);
1012  pScreen->DestroyWindow = KdXVDestroyWindow;
1013
1014  return ret;
1015}
1016
1017
1018static void
1019KdXVWindowExposures(WindowPtr pWin, RegionPtr reg1, RegionPtr reg2)
1020{
1021  ScreenPtr pScreen = pWin->drawable.pScreen;
1022  KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
1023  KdXVWindowPtr WinPriv = GET_KDXV_WINDOW(pWin);
1024  KdXVWindowPtr pPrev;
1025  XvPortRecPrivatePtr pPriv;
1026  Bool AreasExposed;
1027
1028  AreasExposed = (WinPriv && reg1 && REGION_NOTEMPTY(pScreen, reg1));
1029
1030  pScreen->WindowExposures = ScreenPriv->WindowExposures;
1031  (*pScreen->WindowExposures)(pWin, reg1, reg2);
1032  pScreen->WindowExposures = KdXVWindowExposures;
1033
1034  /* filter out XClearWindow/Area */
1035  if (!pWin->valdata) return;
1036
1037  pPrev = NULL;
1038
1039  while(WinPriv) {
1040     pPriv = WinPriv->PortRec;
1041
1042     /* Reput anyone with a reput function */
1043
1044     switch(pPriv->type) {
1045     case XvInputMask:
1046	KdXVReputVideo(pPriv);
1047	break;
1048     case XvOutputMask:
1049	KdXVRegetVideo(pPriv);
1050	break;
1051     default:  /* overlaid still/image*/
1052	if (pPriv->AdaptorRec->ReputImage)
1053	   KdXVReputImage(pPriv);
1054	else if(AreasExposed) {
1055	    KdXVWindowPtr tmp;
1056
1057	    if (pPriv->isOn == XV_ON) {
1058		(*pPriv->AdaptorRec->StopVideo)(
1059		    pPriv->screen, pPriv->DevPriv.ptr, FALSE);
1060		pPriv->isOn = XV_PENDING;
1061	    }
1062	    pPriv->pDraw = NULL;
1063
1064	    if(!pPrev)
1065		dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, WinPriv->next);
1066	    else
1067	       pPrev->next = WinPriv->next;
1068	    tmp = WinPriv;
1069	    WinPriv = WinPriv->next;
1070	    xfree(tmp);
1071	    continue;
1072	}
1073	break;
1074     }
1075     pPrev = WinPriv;
1076     WinPriv = WinPriv->next;
1077  }
1078}
1079
1080
1081static void
1082KdXVClipNotify(WindowPtr pWin, int dx, int dy)
1083{
1084  ScreenPtr pScreen = pWin->drawable.pScreen;
1085  KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
1086  KdXVWindowPtr WinPriv = GET_KDXV_WINDOW(pWin);
1087  KdXVWindowPtr tmp, pPrev = NULL;
1088  XvPortRecPrivatePtr pPriv;
1089  Bool visible = (pWin->visibility == VisibilityUnobscured) ||
1090		 (pWin->visibility == VisibilityPartiallyObscured);
1091
1092  while(WinPriv) {
1093     pPriv = WinPriv->PortRec;
1094
1095     if(pPriv->pCompositeClip && pPriv->FreeCompositeClip)
1096	REGION_DESTROY(pScreen, pPriv->pCompositeClip);
1097
1098     pPriv->pCompositeClip = NULL;
1099
1100     /* Stop everything except images, but stop them too if the
1101	window isn't visible.  But we only remove the images. */
1102
1103     if(pPriv->type || !visible) {
1104	if(pPriv->isOn == XV_ON) {
1105	    (*pPriv->AdaptorRec->StopVideo)(
1106			pPriv->screen, pPriv->DevPriv.ptr, FALSE);
1107	    pPriv->isOn = XV_PENDING;
1108	}
1109
1110	if(!pPriv->type) {  /* overlaid still/image */
1111	    pPriv->pDraw = NULL;
1112
1113	    if(!pPrev)
1114		dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, WinPriv->next);
1115	    else
1116	       pPrev->next = WinPriv->next;
1117	    tmp = WinPriv;
1118	    WinPriv = WinPriv->next;
1119	    xfree(tmp);
1120	    continue;
1121	}
1122     }
1123
1124     pPrev = WinPriv;
1125     WinPriv = WinPriv->next;
1126  }
1127
1128  if(ScreenPriv->ClipNotify) {
1129      pScreen->ClipNotify = ScreenPriv->ClipNotify;
1130      (*pScreen->ClipNotify)(pWin, dx, dy);
1131      pScreen->ClipNotify = KdXVClipNotify;
1132  }
1133}
1134
1135
1136
1137/**** Required XvScreenRec fields ****/
1138
1139static Bool
1140KdXVCloseScreen(int i, ScreenPtr pScreen)
1141{
1142  XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
1143  KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
1144  XvAdaptorPtr pa;
1145  int c;
1146
1147  if(!ScreenPriv) return TRUE;
1148
1149  pScreen->CreateWindow = ScreenPriv->CreateWindow;
1150  pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
1151  pScreen->WindowExposures = ScreenPriv->WindowExposures;
1152  pScreen->ClipNotify = ScreenPriv->ClipNotify;
1153
1154/*   fprintf(stderr,"XV: Unwrapping screen funcs\n"); */
1155
1156  for(c = 0, pa = pxvs->pAdaptors; c < pxvs->nAdaptors; c++, pa++) {
1157       KdXVFreeAdaptor(pa);
1158  }
1159
1160  if(pxvs->pAdaptors)
1161    xfree(pxvs->pAdaptors);
1162
1163  xfree(ScreenPriv);
1164
1165
1166  return TRUE;
1167}
1168
1169
1170static int
1171KdXVQueryAdaptors(
1172   ScreenPtr pScreen,
1173   XvAdaptorPtr *p_pAdaptors,
1174   int *p_nAdaptors
1175){
1176  XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
1177
1178  *p_nAdaptors = pxvs->nAdaptors;
1179  *p_pAdaptors = pxvs->pAdaptors;
1180
1181  return (Success);
1182}
1183
1184static Bool
1185KdXVRunning (ScreenPtr pScreen)
1186{
1187    return (KdXVGeneration == serverGeneration &&
1188	    GET_XV_SCREEN(pScreen) != 0);
1189}
1190
1191Bool
1192KdXVEnable(ScreenPtr pScreen)
1193{
1194    if (!KdXVRunning (pScreen))
1195	return TRUE;
1196
1197    WalkTree(pScreen, KdXVReputAllVideo, 0);
1198
1199    return TRUE;
1200}
1201
1202void
1203KdXVDisable(ScreenPtr pScreen)
1204{
1205    XvScreenPtr pxvs;
1206    KdXVScreenPtr ScreenPriv;
1207    XvAdaptorPtr pAdaptor;
1208    XvPortPtr pPort;
1209    XvPortRecPrivatePtr pPriv;
1210    int i, j;
1211
1212    if (!KdXVRunning (pScreen))
1213	return;
1214
1215    pxvs = GET_XV_SCREEN(pScreen);
1216    ScreenPriv = GET_KDXV_SCREEN(pScreen);
1217
1218    for(i = 0; i < pxvs->nAdaptors; i++) {
1219	pAdaptor = &pxvs->pAdaptors[i];
1220	for(j = 0; j < pAdaptor->nPorts; j++) {
1221	    pPort = &pAdaptor->pPorts[j];
1222	    pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr;
1223	    if(pPriv->isOn > XV_OFF) {
1224
1225		(*pPriv->AdaptorRec->StopVideo)(
1226			pPriv->screen, pPriv->DevPriv.ptr, TRUE);
1227		pPriv->isOn = XV_OFF;
1228
1229		if(pPriv->pCompositeClip && pPriv->FreeCompositeClip)
1230		    REGION_DESTROY(pScreen, pPriv->pCompositeClip);
1231
1232		pPriv->pCompositeClip = NULL;
1233
1234		if(!pPriv->type && pPriv->pDraw) { /* still */
1235		    KdXVRemovePortFromWindow((WindowPtr)pPriv->pDraw, pPriv);
1236		}
1237	    }
1238	}
1239    }
1240}
1241
1242/**** XvAdaptorRec fields ****/
1243
1244static int
1245KdXVAllocatePort(
1246   unsigned long port,
1247   XvPortPtr pPort,
1248   XvPortPtr *ppPort
1249){
1250  *ppPort = pPort;
1251  return Success;
1252}
1253
1254static int
1255KdXVFreePort(XvPortPtr pPort)
1256{
1257  return Success;
1258}
1259
1260static int
1261KdXVPutVideo(
1262   ClientPtr client,
1263   DrawablePtr pDraw,
1264   XvPortPtr pPort,
1265   GCPtr pGC,
1266   INT16 vid_x, INT16 vid_y,
1267   CARD16 vid_w, CARD16 vid_h,
1268   INT16 drw_x, INT16 drw_y,
1269   CARD16 drw_w, CARD16 drw_h
1270){
1271  XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
1272  KdScreenPriv(portPriv->screen->pScreen);
1273  int result;
1274
1275  /* No dumping video to pixmaps... For now anyhow */
1276  if(pDraw->type != DRAWABLE_WINDOW) {
1277      pPort->pDraw = (DrawablePtr)NULL;
1278      return BadAlloc;
1279  }
1280
1281  /* If we are changing windows, unregister our port in the old window */
1282  if(portPriv->pDraw && (portPriv->pDraw != pDraw))
1283     KdXVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
1284
1285  /* Register our port with the new window */
1286  result =  KdXVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
1287  if(result != Success) return result;
1288
1289  portPriv->pDraw = pDraw;
1290  portPriv->type = XvInputMask;
1291
1292  /* save a copy of these parameters */
1293  portPriv->vid_x = vid_x;  portPriv->vid_y = vid_y;
1294  portPriv->vid_w = vid_w;  portPriv->vid_h = vid_h;
1295  portPriv->drw_x = drw_x;  portPriv->drw_y = drw_y;
1296  portPriv->drw_w = drw_w;  portPriv->drw_h = drw_h;
1297
1298  /* make sure we have the most recent copy of the clientClip */
1299  KdXVCopyClip(portPriv, pGC);
1300
1301  /* To indicate to the DI layer that we were successful */
1302  pPort->pDraw = pDraw;
1303
1304  if (!pScreenPriv->enabled) return Success;
1305
1306  return(KdXVReputVideo(portPriv));
1307}
1308
1309static int
1310KdXVPutStill(
1311   ClientPtr client,
1312   DrawablePtr pDraw,
1313   XvPortPtr pPort,
1314   GCPtr pGC,
1315   INT16 vid_x, INT16 vid_y,
1316   CARD16 vid_w, CARD16 vid_h,
1317   INT16 drw_x, INT16 drw_y,
1318   CARD16 drw_w, CARD16 drw_h
1319){
1320  XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
1321  ScreenPtr pScreen = pDraw->pScreen;
1322  KdScreenPriv(pScreen);
1323  KdScreenInfo *screen=pScreenPriv->screen;
1324  RegionRec WinRegion;
1325  RegionRec ClipRegion;
1326  BoxRec WinBox;
1327  int ret = Success;
1328  Bool clippedAway = FALSE;
1329
1330  if (pDraw->type != DRAWABLE_WINDOW)
1331      return BadAlloc;
1332
1333  if (!pScreenPriv->enabled) return Success;
1334
1335  WinBox.x1 = pDraw->x + drw_x;
1336  WinBox.y1 = pDraw->y + drw_y;
1337  WinBox.x2 = WinBox.x1 + drw_w;
1338  WinBox.y2 = WinBox.y1 + drw_h;
1339
1340  REGION_INIT(pScreen, &WinRegion, &WinBox, 1);
1341  REGION_INIT(pScreen, &ClipRegion, NullBox, 1);
1342  REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, pGC->pCompositeClip);
1343
1344  if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
1345     RegionRec VPReg;
1346     BoxRec VPBox;
1347
1348     VPBox.x1 = 0;
1349     VPBox.y1 = 0;
1350     VPBox.x2 = screen->width;
1351     VPBox.y2 = screen->height;
1352
1353     REGION_INIT(pScreen, &VPReg, &VPBox, 1);
1354     REGION_INTERSECT(Screen, &ClipRegion, &ClipRegion, &VPReg);
1355     REGION_UNINIT(pScreen, &VPReg);
1356  }
1357
1358  if(portPriv->pDraw) {
1359     KdXVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
1360  }
1361
1362  if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) {
1363     clippedAway = TRUE;
1364     goto PUT_STILL_BAILOUT;
1365  }
1366
1367  if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
1368     BoxPtr clipBox = REGION_RECTS(&ClipRegion);
1369     if(  (REGION_NUM_RECTS(&ClipRegion) != 1) ||
1370	  (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
1371	  (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2))
1372     {
1373	  clippedAway = TRUE;
1374          goto PUT_STILL_BAILOUT;
1375     }
1376  }
1377
1378  if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
1379     REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion);
1380  }
1381
1382  ret = (*portPriv->AdaptorRec->PutStill)(portPriv->screen, pDraw,
1383		vid_x, vid_y, WinBox.x1, WinBox.y1,
1384		vid_w, vid_h, drw_w, drw_h,
1385		&ClipRegion, portPriv->DevPriv.ptr);
1386
1387  if((ret == Success) &&
1388	(portPriv->AdaptorRec->flags & VIDEO_OVERLAID_STILLS)) {
1389
1390     KdXVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
1391     portPriv->isOn = XV_ON;
1392     portPriv->pDraw = pDraw;
1393     portPriv->drw_x = drw_x;  portPriv->drw_y = drw_y;
1394     portPriv->drw_w = drw_w;  portPriv->drw_h = drw_h;
1395     portPriv->type = 0;  /* no mask means it's transient and should
1396			     not be reput once it's removed */
1397     pPort->pDraw = pDraw;  /* make sure we can get stop requests */
1398  }
1399
1400PUT_STILL_BAILOUT:
1401
1402  if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
1403        (*portPriv->AdaptorRec->StopVideo)(
1404                portPriv->screen, portPriv->DevPriv.ptr, FALSE);
1405        portPriv->isOn = XV_PENDING;
1406  }
1407
1408  REGION_UNINIT(pScreen, &WinRegion);
1409  REGION_UNINIT(pScreen, &ClipRegion);
1410
1411  return ret;
1412}
1413
1414static int
1415KdXVGetVideo(
1416   ClientPtr client,
1417   DrawablePtr pDraw,
1418   XvPortPtr pPort,
1419   GCPtr pGC,
1420   INT16 vid_x, INT16 vid_y,
1421   CARD16 vid_w, CARD16 vid_h,
1422   INT16 drw_x, INT16 drw_y,
1423   CARD16 drw_w, CARD16 drw_h
1424){
1425  XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
1426  int result;
1427  KdScreenPriv(portPriv->screen->pScreen);
1428
1429  /* No pixmaps... For now anyhow */
1430  if(pDraw->type != DRAWABLE_WINDOW) {
1431      pPort->pDraw = (DrawablePtr)NULL;
1432      return BadAlloc;
1433  }
1434
1435  /* If we are changing windows, unregister our port in the old window */
1436  if(portPriv->pDraw && (portPriv->pDraw != pDraw))
1437     KdXVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
1438
1439  /* Register our port with the new window */
1440  result =  KdXVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
1441  if(result != Success) return result;
1442
1443  portPriv->pDraw = pDraw;
1444  portPriv->type = XvOutputMask;
1445
1446  /* save a copy of these parameters */
1447  portPriv->vid_x = vid_x;  portPriv->vid_y = vid_y;
1448  portPriv->vid_w = vid_w;  portPriv->vid_h = vid_h;
1449  portPriv->drw_x = drw_x;  portPriv->drw_y = drw_y;
1450  portPriv->drw_w = drw_w;  portPriv->drw_h = drw_h;
1451
1452  /* make sure we have the most recent copy of the clientClip */
1453  KdXVCopyClip(portPriv, pGC);
1454
1455  /* To indicate to the DI layer that we were successful */
1456  pPort->pDraw = pDraw;
1457
1458  if(!pScreenPriv->enabled) return Success;
1459
1460  return(KdXVRegetVideo(portPriv));
1461}
1462
1463static int
1464KdXVGetStill(
1465   ClientPtr client,
1466   DrawablePtr pDraw,
1467   XvPortPtr pPort,
1468   GCPtr pGC,
1469   INT16 vid_x, INT16 vid_y,
1470   CARD16 vid_w, CARD16 vid_h,
1471   INT16 drw_x, INT16 drw_y,
1472   CARD16 drw_w, CARD16 drw_h
1473){
1474  XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
1475  ScreenPtr pScreen = pDraw->pScreen;
1476  KdScreenPriv(pScreen);
1477  RegionRec WinRegion;
1478  RegionRec ClipRegion;
1479  BoxRec WinBox;
1480  int ret = Success;
1481  Bool clippedAway = FALSE;
1482
1483  if (pDraw->type != DRAWABLE_WINDOW)
1484      return BadAlloc;
1485
1486  if(!pScreenPriv->enabled) return Success;
1487
1488  WinBox.x1 = pDraw->x + drw_x;
1489  WinBox.y1 = pDraw->y + drw_y;
1490  WinBox.x2 = WinBox.x1 + drw_w;
1491  WinBox.y2 = WinBox.y1 + drw_h;
1492
1493  REGION_INIT(pScreen, &WinRegion, &WinBox, 1);
1494  REGION_INIT(pScreen, &ClipRegion, NullBox, 1);
1495  REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, pGC->pCompositeClip);
1496
1497  if(portPriv->pDraw) {
1498     KdXVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
1499  }
1500
1501  if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) {
1502     clippedAway = TRUE;
1503     goto GET_STILL_BAILOUT;
1504  }
1505
1506  if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
1507     REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion);
1508  }
1509
1510  ret = (*portPriv->AdaptorRec->GetStill)(portPriv->screen, pDraw,
1511		vid_x, vid_y, WinBox.x1, WinBox.y1,
1512		vid_w, vid_h, drw_w, drw_h,
1513		&ClipRegion, portPriv->DevPriv.ptr);
1514
1515GET_STILL_BAILOUT:
1516
1517  if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
1518        (*portPriv->AdaptorRec->StopVideo)(
1519                portPriv->screen, portPriv->DevPriv.ptr, FALSE);
1520        portPriv->isOn = XV_PENDING;
1521  }
1522
1523  REGION_UNINIT(pScreen, &WinRegion);
1524  REGION_UNINIT(pScreen, &ClipRegion);
1525
1526  return ret;
1527}
1528
1529
1530
1531static int
1532KdXVStopVideo(
1533   ClientPtr client,
1534   XvPortPtr pPort,
1535   DrawablePtr pDraw
1536){
1537  XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
1538  KdScreenPriv(portPriv->screen->pScreen);
1539
1540  if(pDraw->type != DRAWABLE_WINDOW)
1541      return BadAlloc;
1542
1543  KdXVRemovePortFromWindow((WindowPtr)pDraw, portPriv);
1544
1545  if(!pScreenPriv->enabled) return Success;
1546
1547  /* Must free resources. */
1548
1549  if(portPriv->isOn > XV_OFF) {
1550	(*portPriv->AdaptorRec->StopVideo)(
1551		portPriv->screen, portPriv->DevPriv.ptr, TRUE);
1552	portPriv->isOn = XV_OFF;
1553  }
1554
1555  return Success;
1556}
1557
1558static int
1559KdXVSetPortAttribute(
1560   ClientPtr client,
1561   XvPortPtr pPort,
1562   Atom attribute,
1563   INT32 value
1564){
1565  XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
1566
1567  return((*portPriv->AdaptorRec->SetPortAttribute)(portPriv->screen,
1568		attribute, value, portPriv->DevPriv.ptr));
1569}
1570
1571
1572static int
1573KdXVGetPortAttribute(
1574   ClientPtr client,
1575   XvPortPtr pPort,
1576   Atom attribute,
1577   INT32 *p_value
1578){
1579  XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
1580
1581  return((*portPriv->AdaptorRec->GetPortAttribute)(portPriv->screen,
1582		attribute, (int *) p_value, portPriv->DevPriv.ptr));
1583}
1584
1585
1586
1587static int
1588KdXVQueryBestSize(
1589   ClientPtr client,
1590   XvPortPtr pPort,
1591   CARD8 motion,
1592   CARD16 vid_w, CARD16 vid_h,
1593   CARD16 drw_w, CARD16 drw_h,
1594   unsigned int *p_w, unsigned int *p_h
1595){
1596  XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
1597
1598  (*portPriv->AdaptorRec->QueryBestSize)(portPriv->screen,
1599		(Bool)motion, vid_w, vid_h, drw_w, drw_h,
1600		p_w, p_h, portPriv->DevPriv.ptr);
1601
1602  return Success;
1603}
1604
1605
1606static int
1607KdXVPutImage(
1608   ClientPtr client,
1609   DrawablePtr pDraw,
1610   XvPortPtr pPort,
1611   GCPtr pGC,
1612   INT16 src_x, INT16 src_y,
1613   CARD16 src_w, CARD16 src_h,
1614   INT16 drw_x, INT16 drw_y,
1615   CARD16 drw_w, CARD16 drw_h,
1616   XvImagePtr format,
1617   unsigned char* data,
1618   Bool sync,
1619   CARD16 width, CARD16 height
1620){
1621  XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
1622  ScreenPtr pScreen = pDraw->pScreen;
1623  KdScreenPriv(pScreen);
1624  RegionRec WinRegion;
1625  RegionRec ClipRegion;
1626  BoxRec WinBox;
1627  int ret = Success;
1628  Bool clippedAway = FALSE;
1629
1630  if (pDraw->type != DRAWABLE_WINDOW)
1631      return BadAlloc;
1632
1633  if(!pScreenPriv->enabled) return Success;
1634
1635  WinBox.x1 = pDraw->x + drw_x;
1636  WinBox.y1 = pDraw->y + drw_y;
1637  WinBox.x2 = WinBox.x1 + drw_w;
1638  WinBox.y2 = WinBox.y1 + drw_h;
1639
1640  REGION_INIT(pScreen, &WinRegion, &WinBox, 1);
1641  REGION_INIT(pScreen, &ClipRegion, NullBox, 1);
1642  REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, pGC->pCompositeClip);
1643
1644  if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
1645     RegionRec VPReg;
1646     BoxRec VPBox;
1647
1648     VPBox.x1 = 0;
1649     VPBox.y1 = 0;
1650     VPBox.x2 = pScreen->width;
1651     VPBox.y2 = pScreen->height;
1652
1653     REGION_INIT(pScreen, &VPReg, &VPBox, 1);
1654     REGION_INTERSECT(Screen, &ClipRegion, &ClipRegion, &VPReg);
1655     REGION_UNINIT(pScreen, &VPReg);
1656  }
1657
1658  if(portPriv->pDraw) {
1659     KdXVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
1660  }
1661
1662  if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) {
1663     clippedAway = TRUE;
1664     goto PUT_IMAGE_BAILOUT;
1665  }
1666
1667  if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
1668     BoxPtr clipBox = REGION_RECTS(&ClipRegion);
1669     if(  (REGION_NUM_RECTS(&ClipRegion) != 1) ||
1670	  (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
1671	  (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2))
1672     {
1673	  clippedAway = TRUE;
1674          goto PUT_IMAGE_BAILOUT;
1675     }
1676  }
1677
1678  if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
1679     REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion);
1680  }
1681
1682  ret = (*portPriv->AdaptorRec->PutImage)(portPriv->screen, pDraw,
1683		src_x, src_y, WinBox.x1, WinBox.y1,
1684		src_w, src_h, drw_w, drw_h, format->id, data, width, height,
1685		sync, &ClipRegion, portPriv->DevPriv.ptr);
1686
1687  if((ret == Success) &&
1688	(portPriv->AdaptorRec->flags & VIDEO_OVERLAID_IMAGES)) {
1689
1690     KdXVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
1691     portPriv->isOn = XV_ON;
1692     portPriv->pDraw = pDraw;
1693     portPriv->drw_x = drw_x;  portPriv->drw_y = drw_y;
1694     portPriv->drw_w = drw_w;  portPriv->drw_h = drw_h;
1695     portPriv->type = 0;  /* no mask means it's transient and should
1696			     not be reput once it's removed */
1697     pPort->pDraw = pDraw;  /* make sure we can get stop requests */
1698  }
1699
1700PUT_IMAGE_BAILOUT:
1701
1702  if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
1703        (*portPriv->AdaptorRec->StopVideo)(
1704                portPriv->screen, portPriv->DevPriv.ptr, FALSE);
1705        portPriv->isOn = XV_PENDING;
1706  }
1707
1708  REGION_UNINIT(pScreen, &WinRegion);
1709  REGION_UNINIT(pScreen, &ClipRegion);
1710
1711  return ret;
1712}
1713
1714
1715static  int
1716KdXVQueryImageAttributes(
1717   ClientPtr client,
1718   XvPortPtr pPort,
1719   XvImagePtr format,
1720   CARD16 *width,
1721   CARD16 *height,
1722   int *pitches,
1723   int *offsets
1724){
1725  XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
1726
1727  return (*portPriv->AdaptorRec->QueryImageAttributes)(portPriv->screen,
1728			format->id, width, height, pitches, offsets);
1729}
1730
1731
1732/****************  Common video manipulation functions *******************/
1733
1734void
1735KdXVCopyPackedData(KdScreenInfo *screen, CARD8 *src, CARD8 *dst, int randr,
1736    int srcPitch, int dstPitch, int srcW, int srcH, int top, int left,
1737    int h, int w)
1738{
1739    int srcDown = srcPitch, srcRight = 2, srcNext;
1740    int p;
1741
1742    switch (randr & RR_Rotate_All) {
1743    case RR_Rotate_0:
1744	srcDown = srcPitch;
1745	srcRight = 2;
1746	break;
1747    case RR_Rotate_90:
1748	src += (srcH - 1) * 2;
1749	srcDown = -2;
1750	srcRight = srcPitch;
1751	break;
1752    case RR_Rotate_180:
1753	src += srcPitch * (srcH - 1) + (srcW - 1) * 2;
1754	srcDown = -srcPitch;
1755	srcRight = -2;
1756	break;
1757    case RR_Rotate_270:
1758	src += srcPitch * (srcW - 1);
1759	srcDown = 2;
1760	srcRight = -srcPitch;
1761	break;
1762    }
1763
1764    src = src + top * srcDown + left * srcRight;
1765
1766    w >>= 1;
1767    /* srcRight >>= 1; */
1768    srcNext = srcRight >> 1;
1769    while (h--) {
1770	CARD16 *s = (CARD16 *)src;
1771	CARD32 *d = (CARD32 *)dst;
1772	p = w;
1773	while (p--) {
1774	    *d++ = s[0] | (s[srcNext] << 16);
1775	    s += srcRight;
1776	}
1777	src += srcPitch;
1778	dst += dstPitch;
1779    }
1780}
1781
1782void
1783KdXVCopyPlanarData(KdScreenInfo *screen, CARD8 *src, CARD8 *dst, int randr,
1784    int srcPitch, int srcPitch2, int dstPitch, int srcW, int srcH, int height,
1785    int top, int left, int h, int w, int id)
1786{
1787    int i, j;
1788    CARD8 *src1, *src2, *src3, *dst1;
1789    int srcDown = srcPitch, srcDown2 = srcPitch2;
1790    int srcRight = 2, srcRight2 = 1, srcNext = 1;
1791
1792    /* compute source data pointers */
1793    src1 = src;
1794    src2 = src1 + height * srcPitch;
1795    src3 = src2 + (height >> 1) * srcPitch2;
1796    switch (randr & RR_Rotate_All) {
1797    case RR_Rotate_0:
1798	srcDown = srcPitch;
1799	srcDown2 = srcPitch2;
1800	srcRight = 2;
1801	srcRight2 = 1;
1802	srcNext = 1;
1803	break;
1804    case RR_Rotate_90:
1805	src1 = src1 + srcH - 1;
1806	src2 = src2 + (srcH >> 1) - 1;
1807	src3 = src3 + (srcH >> 1) - 1;
1808	srcDown = -1;
1809	srcDown2 = -1;
1810	srcRight = srcPitch * 2;
1811	srcRight2 = srcPitch2;
1812	srcNext = srcPitch;
1813	break;
1814    case RR_Rotate_180:
1815	src1 = src1 + srcPitch * (srcH - 1) + (srcW - 1);
1816	src2 = src2 + srcPitch2 * ((srcH >> 1) - 1) + ((srcW >> 1) - 1);
1817	src3 = src3 + srcPitch2 * ((srcH >> 1) - 1) + ((srcW >> 1) - 1);
1818	srcDown = -srcPitch;
1819	srcDown2 = -srcPitch2;
1820	srcRight = -2;
1821	srcRight2 = -1;
1822	srcNext = -1;
1823	break;
1824    case RR_Rotate_270:
1825	src1 = src1 + srcPitch * (srcW - 1);
1826	src2 = src2 + srcPitch2 * ((srcW >> 1) - 1);
1827	src3 = src3 + srcPitch2 * ((srcW >> 1) - 1);
1828	srcDown = 1;
1829	srcDown2 = 1;
1830	srcRight = -srcPitch * 2;
1831	srcRight2 = -srcPitch2;
1832	srcNext = -srcPitch;
1833	break;
1834    }
1835
1836    /* adjust for origin */
1837    src1 += top * srcDown + left * srcNext;
1838    src2 += (top >> 1) * srcDown2 + (left >> 1) * srcRight2;
1839    src3 += (top >> 1) * srcDown2 + (left >> 1) * srcRight2;
1840
1841    if (id == FOURCC_I420) {
1842	CARD8 *srct = src2;
1843	src2 = src3;
1844	src3 = srct;
1845    }
1846
1847    dst1 = dst;
1848
1849    w >>= 1;
1850    for (j = 0; j < h; j++) {
1851	CARD32 *dst = (CARD32 *)dst1;
1852	CARD8 *s1l = src1;
1853	CARD8 *s1r = src1 + srcNext;
1854	CARD8 *s2 = src2;
1855	CARD8 *s3 = src3;
1856
1857	for (i = 0; i < w; i++) {
1858	    *dst++ = *s1l | (*s1r << 16) | (*s3 << 8) | (*s2 << 24);
1859	    s1l += srcRight;
1860	    s1r += srcRight;
1861	    s2 += srcRight2;
1862	    s3 += srcRight2;
1863	}
1864	src1 += srcDown;
1865	dst1 += dstPitch;
1866	if (j & 1) {
1867	    src2 += srcDown2;
1868	    src3 += srcDown2;
1869	}
1870    }
1871}
1872
1873void
1874KXVPaintRegion (DrawablePtr pDraw, RegionPtr pRgn, Pixel fg)
1875{
1876    GCPtr	pGC;
1877    CARD32    	val[2];
1878    xRectangle	*rects, *r;
1879    BoxPtr	pBox = REGION_RECTS (pRgn);
1880    int		nBox = REGION_NUM_RECTS (pRgn);
1881
1882    rects = xalloc (nBox * sizeof (xRectangle));
1883    if (!rects)
1884	goto bail0;
1885    r = rects;
1886    while (nBox--)
1887    {
1888	r->x = pBox->x1 - pDraw->x;
1889	r->y = pBox->y1 - pDraw->y;
1890	r->width = pBox->x2 - pBox->x1;
1891	r->height = pBox->y2 - pBox->y1;
1892	r++;
1893	pBox++;
1894    }
1895
1896    pGC = GetScratchGC (pDraw->depth, pDraw->pScreen);
1897    if (!pGC)
1898	goto bail1;
1899
1900    val[0] = fg;
1901    val[1] = IncludeInferiors;
1902    ChangeGC (pGC, GCForeground|GCSubwindowMode, val);
1903
1904    ValidateGC (pDraw, pGC);
1905
1906    (*pGC->ops->PolyFillRect) (pDraw, pGC,
1907			       REGION_NUM_RECTS (pRgn), rects);
1908
1909    FreeScratchGC (pGC);
1910bail1:
1911    xfree (rects);
1912bail0:
1913    ;
1914}
1915