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