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