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