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 
9 All rights reserved.
10 
11 Permission is hereby granted, free of charge, to any person obtaining
12 a copy of this software and associated documentation files (the
13 "Software"), to deal in the Software without restriction, including
14 without limitation the rights to use, copy, modify, merge, publish,
15 distribute, and/or sell copies of the Software, and to permit persons
16 to whom the Software is furnished to do so, provided that the above
17 copyright notice(s) and this permission notice appear in all copies of
18 the Software and that both the above copyright notice(s) and this
19 permission notice appear in supporting documentation.
20 
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
24 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
25 HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
26 SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
27 RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
28 CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
29 CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
30 
31 Except as contained in this notice, the name of a copyright holder
32 shall not be used in advertising or otherwise to promote the sale, use
33 or other dealings in this Software without prior written authorization
34 of the copyright holder.
35 
36 */
37 
38 #ifdef HAVE_DIX_CONFIG_H
39 #include <dix-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 /* XvAdaptorRec fields */
60 
61 static int KdXVPutVideo(DrawablePtr, XvPortPtr, GCPtr,
62                         INT16, INT16, CARD16, CARD16,
63                         INT16, INT16, CARD16, CARD16);
64 static int KdXVPutStill(DrawablePtr, XvPortPtr, GCPtr,
65                         INT16, INT16, CARD16, CARD16,
66                         INT16, INT16, CARD16, CARD16);
67 static int KdXVGetVideo(DrawablePtr, XvPortPtr, GCPtr,
68                         INT16, INT16, CARD16, CARD16,
69                         INT16, INT16, CARD16, CARD16);
70 static int KdXVGetStill(DrawablePtr, XvPortPtr, GCPtr,
71                         INT16, INT16, CARD16, CARD16,
72                         INT16, INT16, CARD16, CARD16);
73 static int KdXVStopVideo(XvPortPtr, DrawablePtr);
74 static int KdXVSetPortAttribute(XvPortPtr, Atom, INT32);
75 static int KdXVGetPortAttribute(XvPortPtr, Atom, INT32 *);
76 static int KdXVQueryBestSize(XvPortPtr, CARD8,
77                              CARD16, CARD16, CARD16, CARD16,
78                              unsigned int *, unsigned int *);
79 static int KdXVPutImage(DrawablePtr, XvPortPtr, GCPtr,
80                         INT16, INT16, CARD16, CARD16,
81                         INT16, INT16, CARD16, CARD16,
82                         XvImagePtr, unsigned char *, Bool, CARD16, CARD16);
83 static int KdXVQueryImageAttributes(XvPortPtr, XvImagePtr,
84                                     CARD16 *, CARD16 *, int *, int *);
85 
86 /* ScreenRec fields */
87 
88 static Bool KdXVDestroyWindow(WindowPtr pWin);
89 static void KdXVWindowExposures(WindowPtr pWin, RegionPtr r1);
90 static void KdXVClipNotify(WindowPtr pWin, int dx, int dy);
91 static Bool KdXVCloseScreen(ScreenPtr);
92 
93 /* misc */
94 static Bool KdXVInitAdaptors(ScreenPtr, KdVideoAdaptorPtr, int);
95 
96 static DevPrivateKeyRec KdXVWindowKeyRec;
97 
98 #define KdXVWindowKey (&KdXVWindowKeyRec)
99 static DevPrivateKey KdXvScreenKey;
100 static DevPrivateKeyRec KdXVScreenPrivateKey;
101 static unsigned long KdXVGeneration = 0;
102 static unsigned long PortResource = 0;
103 
104 #define GET_XV_SCREEN(pScreen) ((XvScreenPtr) \
105     dixLookupPrivate(&(pScreen)->devPrivates, KdXvScreenKey))
106 
107 #define GET_KDXV_SCREEN(pScreen) \
108     ((KdXVScreenPtr)(dixGetPrivate(&pScreen->devPrivates, &KdXVScreenPrivateKey)))
109 
110 #define GET_KDXV_WINDOW(pWin) ((KdXVWindowPtr) \
111     dixLookupPrivate(&(pWin)->devPrivates, KdXVWindowKey))
112 
113 Bool
KdXVScreenInit(ScreenPtr pScreen,KdVideoAdaptorPtr adaptors,int num)114 KdXVScreenInit(ScreenPtr pScreen, KdVideoAdaptorPtr adaptors, int num)
115 {
116     KdXVScreenPtr ScreenPriv;
117 
118 /*   fprintf(stderr,"KdXVScreenInit initializing %d adaptors\n",num); */
119 
120     if (KdXVGeneration != serverGeneration)
121         KdXVGeneration = serverGeneration;
122 
123     if (noXvExtension)
124         return FALSE;
125 
126     if (!dixRegisterPrivateKey(&KdXVWindowKeyRec, PRIVATE_WINDOW, 0))
127         return FALSE;
128     if (!dixRegisterPrivateKey(&KdXVScreenPrivateKey, PRIVATE_SCREEN, 0))
129         return FALSE;
130 
131     if (Success != XvScreenInit(pScreen))
132         return FALSE;
133 
134     KdXvScreenKey = XvGetScreenKey();
135     PortResource = XvGetRTPort();
136 
137     ScreenPriv = malloc(sizeof(KdXVScreenRec));
138     dixSetPrivate(&pScreen->devPrivates, &KdXVScreenPrivateKey, ScreenPriv);
139 
140     if (!ScreenPriv)
141         return FALSE;
142 
143     ScreenPriv->DestroyWindow = pScreen->DestroyWindow;
144     ScreenPriv->WindowExposures = pScreen->WindowExposures;
145     ScreenPriv->ClipNotify = pScreen->ClipNotify;
146     ScreenPriv->CloseScreen = pScreen->CloseScreen;
147 
148 /*   fprintf(stderr,"XV: Wrapping screen funcs\n"); */
149 
150     pScreen->DestroyWindow = KdXVDestroyWindow;
151     pScreen->WindowExposures = KdXVWindowExposures;
152     pScreen->ClipNotify = KdXVClipNotify;
153     pScreen->CloseScreen = KdXVCloseScreen;
154 
155     if (!KdXVInitAdaptors(pScreen, adaptors, num))
156         return FALSE;
157 
158     return TRUE;
159 }
160 
161 static void
KdXVFreeAdaptor(XvAdaptorPtr pAdaptor)162 KdXVFreeAdaptor(XvAdaptorPtr pAdaptor)
163 {
164     int i;
165 
166     if (pAdaptor->pPorts) {
167         XvPortPtr pPort = pAdaptor->pPorts;
168         XvPortRecPrivatePtr pPriv;
169 
170         for (i = 0; i < pAdaptor->nPorts; i++, pPort++) {
171             pPriv = (XvPortRecPrivatePtr) pPort->devPriv.ptr;
172             if (pPriv) {
173                 if (pPriv->clientClip)
174                     RegionDestroy(pPriv->clientClip);
175                 if (pPriv->pCompositeClip && pPriv->FreeCompositeClip)
176                     RegionDestroy(pPriv->pCompositeClip);
177                 free(pPriv);
178             }
179         }
180     }
181 
182     XvFreeAdaptor(pAdaptor);
183 }
184 
185 static Bool
KdXVInitAdaptors(ScreenPtr pScreen,KdVideoAdaptorPtr infoPtr,int number)186 KdXVInitAdaptors(ScreenPtr pScreen, KdVideoAdaptorPtr infoPtr, int number)
187 {
188     KdScreenPriv(pScreen);
189     KdScreenInfo *screen = pScreenPriv->screen;
190 
191     XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
192     KdVideoAdaptorPtr adaptorPtr;
193     XvAdaptorPtr pAdaptor, pa;
194     XvAdaptorRecPrivatePtr adaptorPriv;
195     int na, numAdaptor;
196     XvPortRecPrivatePtr portPriv;
197     XvPortPtr pPort, pp;
198     int numPort;
199     KdVideoFormatPtr formatPtr;
200     XvFormatPtr pFormat, pf;
201     int numFormat, totFormat;
202     KdVideoEncodingPtr encodingPtr;
203     XvEncodingPtr pEncode, pe;
204     int numVisuals;
205     VisualPtr pVisual;
206     int i;
207 
208     pxvs->nAdaptors = 0;
209     pxvs->pAdaptors = NULL;
210 
211     if (!(pAdaptor = calloc(number, sizeof(XvAdaptorRec))))
212         return FALSE;
213 
214     for (pa = pAdaptor, na = 0, numAdaptor = 0; na < number; na++, adaptorPtr++) {
215         adaptorPtr = &infoPtr[na];
216 
217         if (!adaptorPtr->StopVideo || !adaptorPtr->SetPortAttribute ||
218             !adaptorPtr->GetPortAttribute || !adaptorPtr->QueryBestSize)
219             continue;
220 
221         /* client libs expect at least one encoding */
222         if (!adaptorPtr->nEncodings || !adaptorPtr->pEncodings)
223             continue;
224 
225         pa->type = adaptorPtr->type;
226 
227         if (!adaptorPtr->PutVideo && !adaptorPtr->GetVideo)
228             pa->type &= ~XvVideoMask;
229 
230         if (!adaptorPtr->PutStill && !adaptorPtr->GetStill)
231             pa->type &= ~XvStillMask;
232 
233         if (!adaptorPtr->PutImage || !adaptorPtr->QueryImageAttributes)
234             pa->type &= ~XvImageMask;
235 
236         if (!adaptorPtr->PutVideo && !adaptorPtr->PutImage &&
237             !adaptorPtr->PutStill)
238             pa->type &= ~XvInputMask;
239 
240         if (!adaptorPtr->GetVideo && !adaptorPtr->GetStill)
241             pa->type &= ~XvOutputMask;
242 
243         if (!(adaptorPtr->type & (XvPixmapMask | XvWindowMask)))
244             continue;
245         if (!(adaptorPtr->type & (XvImageMask | XvVideoMask | XvStillMask)))
246             continue;
247 
248         pa->pScreen = pScreen;
249         pa->ddPutVideo = KdXVPutVideo;
250         pa->ddPutStill = KdXVPutStill;
251         pa->ddGetVideo = KdXVGetVideo;
252         pa->ddGetStill = KdXVGetStill;
253         pa->ddStopVideo = KdXVStopVideo;
254         pa->ddPutImage = KdXVPutImage;
255         pa->ddSetPortAttribute = KdXVSetPortAttribute;
256         pa->ddGetPortAttribute = KdXVGetPortAttribute;
257         pa->ddQueryBestSize = KdXVQueryBestSize;
258         pa->ddQueryImageAttributes = KdXVQueryImageAttributes;
259         pa->name = strdup(adaptorPtr->name);
260 
261         if (adaptorPtr->nEncodings &&
262             (pEncode = calloc(adaptorPtr->nEncodings, sizeof(XvEncodingRec)))) {
263 
264             for (pe = pEncode, encodingPtr = adaptorPtr->pEncodings, i = 0;
265                  i < adaptorPtr->nEncodings; pe++, i++, encodingPtr++) {
266                 pe->id = encodingPtr->id;
267                 pe->pScreen = pScreen;
268                 pe->name = strdup(encodingPtr->name);
269                 pe->width = encodingPtr->width;
270                 pe->height = encodingPtr->height;
271                 pe->rate.numerator = encodingPtr->rate.numerator;
272                 pe->rate.denominator = encodingPtr->rate.denominator;
273             }
274             pa->nEncodings = adaptorPtr->nEncodings;
275             pa->pEncodings = pEncode;
276         }
277 
278         if (adaptorPtr->nImages &&
279             (pa->pImages = calloc(adaptorPtr->nImages, sizeof(XvImageRec)))) {
280             memcpy(pa->pImages, adaptorPtr->pImages,
281                    adaptorPtr->nImages * sizeof(XvImageRec));
282             pa->nImages = adaptorPtr->nImages;
283         }
284 
285         if (adaptorPtr->nAttributes &&
286             (pa->pAttributes = calloc(adaptorPtr->nAttributes,
287                                       sizeof(XvAttributeRec)))) {
288             memcpy(pa->pAttributes, adaptorPtr->pAttributes,
289                    adaptorPtr->nAttributes * sizeof(XvAttributeRec));
290 
291             for (i = 0; i < adaptorPtr->nAttributes; i++) {
292                 pa->pAttributes[i].name =
293                     strdup(adaptorPtr->pAttributes[i].name);
294             }
295 
296             pa->nAttributes = adaptorPtr->nAttributes;
297         }
298 
299         totFormat = adaptorPtr->nFormats;
300 
301         if (!(pFormat = calloc(totFormat, sizeof(XvFormatRec)))) {
302             KdXVFreeAdaptor(pa);
303             continue;
304         }
305         for (pf = pFormat, i = 0, numFormat = 0, formatPtr =
306              adaptorPtr->pFormats; i < adaptorPtr->nFormats; i++, formatPtr++) {
307             numVisuals = pScreen->numVisuals;
308             pVisual = pScreen->visuals;
309 
310             while (numVisuals--) {
311                 if ((pVisual->class == formatPtr->class) &&
312                     (pVisual->nplanes == formatPtr->depth)) {
313 
314                     if (numFormat >= totFormat) {
315                         void *moreSpace;
316 
317                         totFormat *= 2;
318                         moreSpace = reallocarray(pFormat, totFormat,
319                                                  sizeof(XvFormatRec));
320                         if (!moreSpace)
321                             break;
322                         pFormat = moreSpace;
323                         pf = pFormat + numFormat;
324                     }
325 
326                     pf->visual = pVisual->vid;
327                     pf->depth = formatPtr->depth;
328 
329                     pf++;
330                     numFormat++;
331                 }
332                 pVisual++;
333             }
334         }
335         pa->nFormats = numFormat;
336         pa->pFormats = pFormat;
337         if (!numFormat) {
338             KdXVFreeAdaptor(pa);
339             continue;
340         }
341 
342         if (!(adaptorPriv = calloc(1, sizeof(XvAdaptorRecPrivate)))) {
343             KdXVFreeAdaptor(pa);
344             continue;
345         }
346 
347         adaptorPriv->flags = adaptorPtr->flags;
348         adaptorPriv->PutVideo = adaptorPtr->PutVideo;
349         adaptorPriv->PutStill = adaptorPtr->PutStill;
350         adaptorPriv->GetVideo = adaptorPtr->GetVideo;
351         adaptorPriv->GetStill = adaptorPtr->GetStill;
352         adaptorPriv->StopVideo = adaptorPtr->StopVideo;
353         adaptorPriv->SetPortAttribute = adaptorPtr->SetPortAttribute;
354         adaptorPriv->GetPortAttribute = adaptorPtr->GetPortAttribute;
355         adaptorPriv->QueryBestSize = adaptorPtr->QueryBestSize;
356         adaptorPriv->QueryImageAttributes = adaptorPtr->QueryImageAttributes;
357         adaptorPriv->PutImage = adaptorPtr->PutImage;
358         adaptorPriv->ReputImage = adaptorPtr->ReputImage;
359 
360         pa->devPriv.ptr = (void *) adaptorPriv;
361 
362         if (!(pPort = calloc(adaptorPtr->nPorts, sizeof(XvPortRec)))) {
363             KdXVFreeAdaptor(pa);
364             continue;
365         }
366         for (pp = pPort, i = 0, numPort = 0; i < adaptorPtr->nPorts; i++) {
367 
368             if (!(pp->id = FakeClientID(0)))
369                 continue;
370 
371             if (!(portPriv = calloc(1, sizeof(XvPortRecPrivate))))
372                 continue;
373 
374             if (!AddResource(pp->id, PortResource, pp)) {
375                 free(portPriv);
376                 continue;
377             }
378 
379             pp->pAdaptor = pa;
380             pp->pNotify = (XvPortNotifyPtr) NULL;
381             pp->pDraw = (DrawablePtr) NULL;
382             pp->client = (ClientPtr) NULL;
383             pp->grab.client = (ClientPtr) NULL;
384             pp->time = currentTime;
385             pp->devPriv.ptr = portPriv;
386 
387             portPriv->screen = screen;
388             portPriv->AdaptorRec = adaptorPriv;
389             portPriv->DevPriv.ptr = adaptorPtr->pPortPrivates[i].ptr;
390 
391             pp++;
392             numPort++;
393         }
394         pa->nPorts = numPort;
395         pa->pPorts = pPort;
396         if (!numPort) {
397             KdXVFreeAdaptor(pa);
398             continue;
399         }
400 
401         pa->base_id = pPort->id;
402 
403         pa++;
404         numAdaptor++;
405     }
406 
407     if (numAdaptor) {
408         pxvs->nAdaptors = numAdaptor;
409         pxvs->pAdaptors = pAdaptor;
410     }
411     else {
412         free(pAdaptor);
413         return FALSE;
414     }
415 
416     return TRUE;
417 }
418 
419 /* Video should be clipped to the intersection of the window cliplist
420    and the client cliplist specified in the GC for which the video was
421    initialized.  When we need to reclip a window, the GC that started
422    the video may not even be around anymore.  That's why we save the
423    client clip from the GC when the video is initialized.  We then
424    use KdXVUpdateCompositeClip to calculate the new composite clip
425    when we need it.  This is different from what DEC did.  They saved
426    the GC and used it's clip list when they needed to reclip the window,
427    even if the client clip was different from the one the video was
428    initialized with.  If the original GC was destroyed, they had to stop
429    the video.  I like the new method better (MArk).
430 
431    This function only works for windows.  Will need to rewrite when
432    (if) we support pixmap rendering.
433 */
434 
435 static void
KdXVUpdateCompositeClip(XvPortRecPrivatePtr portPriv)436 KdXVUpdateCompositeClip(XvPortRecPrivatePtr portPriv)
437 {
438     RegionPtr pregWin, pCompositeClip;
439     WindowPtr pWin;
440     Bool freeCompClip = FALSE;
441 
442     if (portPriv->pCompositeClip)
443         return;
444 
445     pWin = (WindowPtr) portPriv->pDraw;
446 
447     /* get window clip list */
448     if (portPriv->subWindowMode == IncludeInferiors) {
449         pregWin = NotClippedByChildren(pWin);
450         freeCompClip = TRUE;
451     }
452     else
453         pregWin = &pWin->clipList;
454 
455     if (!portPriv->clientClip) {
456         portPriv->pCompositeClip = pregWin;
457         portPriv->FreeCompositeClip = freeCompClip;
458         return;
459     }
460 
461     pCompositeClip = RegionCreate(NullBox, 1);
462     RegionCopy(pCompositeClip, portPriv->clientClip);
463     RegionTranslate(pCompositeClip,
464                     portPriv->pDraw->x + portPriv->clipOrg.x,
465                     portPriv->pDraw->y + portPriv->clipOrg.y);
466     RegionIntersect(pCompositeClip, pregWin, pCompositeClip);
467 
468     portPriv->pCompositeClip = pCompositeClip;
469     portPriv->FreeCompositeClip = TRUE;
470 
471     if (freeCompClip) {
472         RegionDestroy(pregWin);
473     }
474 }
475 
476 /* Save the current clientClip and update the CompositeClip whenever
477    we have a fresh GC */
478 
479 static void
KdXVCopyClip(XvPortRecPrivatePtr portPriv,GCPtr pGC)480 KdXVCopyClip(XvPortRecPrivatePtr portPriv, GCPtr pGC)
481 {
482     /* copy the new clip if it exists */
483     if (pGC->clientClip) {
484         if (!portPriv->clientClip)
485             portPriv->clientClip = RegionCreate(NullBox, 1);
486         /* Note: this is in window coordinates */
487         RegionCopy(portPriv->clientClip, pGC->clientClip);
488     }
489     else if (portPriv->clientClip) {    /* free the old clientClip */
490         RegionDestroy(portPriv->clientClip);
491         portPriv->clientClip = NULL;
492     }
493 
494     /* get rid of the old clip list */
495     if (portPriv->pCompositeClip && portPriv->FreeCompositeClip) {
496         RegionDestroy(portPriv->pCompositeClip);
497     }
498 
499     portPriv->clipOrg = pGC->clipOrg;
500     portPriv->pCompositeClip = pGC->pCompositeClip;
501     portPriv->FreeCompositeClip = FALSE;
502     portPriv->subWindowMode = pGC->subWindowMode;
503 }
504 
505 static int
KdXVRegetVideo(XvPortRecPrivatePtr portPriv)506 KdXVRegetVideo(XvPortRecPrivatePtr portPriv)
507 {
508     RegionRec WinRegion;
509     RegionRec ClipRegion;
510     BoxRec WinBox;
511     int ret = Success;
512     Bool clippedAway = FALSE;
513 
514     KdXVUpdateCompositeClip(portPriv);
515 
516     /* translate the video region to the screen */
517     WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
518     WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
519     WinBox.x2 = WinBox.x1 + portPriv->drw_w;
520     WinBox.y2 = WinBox.y1 + portPriv->drw_h;
521 
522     /* clip to the window composite clip */
523     RegionInit(&WinRegion, &WinBox, 1);
524     RegionInit(&ClipRegion, NullBox, 1);
525     RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
526 
527     /* that's all if it's totally obscured */
528     if (!RegionNotEmpty(&ClipRegion)) {
529         clippedAway = TRUE;
530         goto CLIP_VIDEO_BAILOUT;
531     }
532 
533     ret = (*portPriv->AdaptorRec->GetVideo) (portPriv->screen, portPriv->pDraw,
534                                              portPriv->vid_x, portPriv->vid_y,
535                                              WinBox.x1, WinBox.y1,
536                                              portPriv->vid_w, portPriv->vid_h,
537                                              portPriv->drw_w, portPriv->drw_h,
538                                              &ClipRegion,
539                                              portPriv->DevPriv.ptr);
540 
541     if (ret == Success)
542         portPriv->isOn = XV_ON;
543 
544  CLIP_VIDEO_BAILOUT:
545 
546     if ((clippedAway || (ret != Success)) && portPriv->isOn == XV_ON) {
547         (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
548                                             portPriv->DevPriv.ptr, FALSE);
549         portPriv->isOn = XV_PENDING;
550     }
551 
552     /* This clip was copied and only good for one shot */
553     if (!portPriv->FreeCompositeClip)
554         portPriv->pCompositeClip = NULL;
555 
556     RegionUninit(&WinRegion);
557     RegionUninit(&ClipRegion);
558 
559     return ret;
560 }
561 
562 static int
KdXVReputVideo(XvPortRecPrivatePtr portPriv)563 KdXVReputVideo(XvPortRecPrivatePtr portPriv)
564 {
565     RegionRec WinRegion;
566     RegionRec ClipRegion;
567     BoxRec WinBox;
568     ScreenPtr pScreen = portPriv->pDraw->pScreen;
569 
570     KdScreenPriv(pScreen);
571     KdScreenInfo *screen = pScreenPriv->screen;
572     int ret = Success;
573     Bool clippedAway = FALSE;
574 
575     KdXVUpdateCompositeClip(portPriv);
576 
577     /* translate the video region to the screen */
578     WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
579     WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
580     WinBox.x2 = WinBox.x1 + portPriv->drw_w;
581     WinBox.y2 = WinBox.y1 + portPriv->drw_h;
582 
583     /* clip to the window composite clip */
584     RegionInit(&WinRegion, &WinBox, 1);
585     RegionInit(&ClipRegion, NullBox, 1);
586     RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
587 
588     /* clip and translate to the viewport */
589     if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
590         RegionRec VPReg;
591         BoxRec VPBox;
592 
593         VPBox.x1 = 0;
594         VPBox.y1 = 0;
595         VPBox.x2 = screen->width;
596         VPBox.y2 = screen->height;
597 
598         RegionInit(&VPReg, &VPBox, 1);
599         RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
600         RegionUninit(&VPReg);
601     }
602 
603     /* that's all if it's totally obscured */
604     if (!RegionNotEmpty(&ClipRegion)) {
605         clippedAway = TRUE;
606         goto CLIP_VIDEO_BAILOUT;
607     }
608 
609     ret = (*portPriv->AdaptorRec->PutVideo) (portPriv->screen, portPriv->pDraw,
610                                              portPriv->vid_x, portPriv->vid_y,
611                                              WinBox.x1, WinBox.y1,
612                                              portPriv->vid_w, portPriv->vid_h,
613                                              portPriv->drw_w, portPriv->drw_h,
614                                              &ClipRegion,
615                                              portPriv->DevPriv.ptr);
616 
617     if (ret == Success)
618         portPriv->isOn = XV_ON;
619 
620  CLIP_VIDEO_BAILOUT:
621 
622     if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
623         (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
624                                             portPriv->DevPriv.ptr, FALSE);
625         portPriv->isOn = XV_PENDING;
626     }
627 
628     /* This clip was copied and only good for one shot */
629     if (!portPriv->FreeCompositeClip)
630         portPriv->pCompositeClip = NULL;
631 
632     RegionUninit(&WinRegion);
633     RegionUninit(&ClipRegion);
634 
635     return ret;
636 }
637 
638 static int
KdXVReputImage(XvPortRecPrivatePtr portPriv)639 KdXVReputImage(XvPortRecPrivatePtr portPriv)
640 {
641     RegionRec WinRegion;
642     RegionRec ClipRegion;
643     BoxRec WinBox;
644     ScreenPtr pScreen = portPriv->pDraw->pScreen;
645 
646     KdScreenPriv(pScreen);
647     KdScreenInfo *screen = pScreenPriv->screen;
648     int ret = Success;
649     Bool clippedAway = FALSE;
650 
651     KdXVUpdateCompositeClip(portPriv);
652 
653     /* translate the video region to the screen */
654     WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
655     WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
656     WinBox.x2 = WinBox.x1 + portPriv->drw_w;
657     WinBox.y2 = WinBox.y1 + portPriv->drw_h;
658 
659     /* clip to the window composite clip */
660     RegionInit(&WinRegion, &WinBox, 1);
661     RegionInit(&ClipRegion, NullBox, 1);
662     RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
663 
664     /* clip and translate to the viewport */
665     if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
666         RegionRec VPReg;
667         BoxRec VPBox;
668 
669         VPBox.x1 = 0;
670         VPBox.y1 = 0;
671         VPBox.x2 = screen->width;
672         VPBox.y2 = screen->height;
673 
674         RegionInit(&VPReg, &VPBox, 1);
675         RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
676         RegionUninit(&VPReg);
677     }
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     ret =
686         (*portPriv->AdaptorRec->ReputImage) (portPriv->screen, portPriv->pDraw,
687                                              WinBox.x1, WinBox.y1, &ClipRegion,
688                                              portPriv->DevPriv.ptr);
689 
690     portPriv->isOn = (ret == Success) ? XV_ON : XV_OFF;
691 
692  CLIP_VIDEO_BAILOUT:
693 
694     if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
695         (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
696                                             portPriv->DevPriv.ptr, FALSE);
697         portPriv->isOn = XV_PENDING;
698     }
699 
700     /* This clip was copied and only good for one shot */
701     if (!portPriv->FreeCompositeClip)
702         portPriv->pCompositeClip = NULL;
703 
704     RegionUninit(&WinRegion);
705     RegionUninit(&ClipRegion);
706 
707     return ret;
708 }
709 
710 static int
KdXVEnlistPortInWindow(WindowPtr pWin,XvPortRecPrivatePtr portPriv)711 KdXVEnlistPortInWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
712 {
713     KdXVWindowPtr winPriv, PrivRoot;
714 
715     winPriv = PrivRoot = GET_KDXV_WINDOW(pWin);
716 
717     /* Enlist our port in the window private */
718     while (winPriv) {
719         if (winPriv->PortRec == portPriv)       /* we're already listed */
720             break;
721         winPriv = winPriv->next;
722     }
723 
724     if (!winPriv) {
725         winPriv = malloc(sizeof(KdXVWindowRec));
726         if (!winPriv)
727             return BadAlloc;
728         winPriv->PortRec = portPriv;
729         winPriv->next = PrivRoot;
730         dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, winPriv);
731     }
732     return Success;
733 }
734 
735 static void
KdXVRemovePortFromWindow(WindowPtr pWin,XvPortRecPrivatePtr portPriv)736 KdXVRemovePortFromWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
737 {
738     KdXVWindowPtr winPriv, prevPriv = NULL;
739 
740     winPriv = GET_KDXV_WINDOW(pWin);
741 
742     while (winPriv) {
743         if (winPriv->PortRec == portPriv) {
744             if (prevPriv)
745                 prevPriv->next = winPriv->next;
746             else
747                 dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, winPriv->next);
748             free(winPriv);
749             break;
750         }
751         prevPriv = winPriv;
752         winPriv = winPriv->next;
753     }
754     portPriv->pDraw = NULL;
755 }
756 
757 /****  ScreenRec fields ****/
758 
759 static Bool
KdXVDestroyWindow(WindowPtr pWin)760 KdXVDestroyWindow(WindowPtr pWin)
761 {
762     ScreenPtr pScreen = pWin->drawable.pScreen;
763     KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
764     KdXVWindowPtr tmp, WinPriv = GET_KDXV_WINDOW(pWin);
765     int ret;
766 
767     while (WinPriv) {
768         XvPortRecPrivatePtr pPriv = WinPriv->PortRec;
769 
770         if (pPriv->isOn > XV_OFF) {
771             (*pPriv->AdaptorRec->StopVideo) (pPriv->screen, pPriv->DevPriv.ptr,
772                                              TRUE);
773             pPriv->isOn = XV_OFF;
774         }
775 
776         pPriv->pDraw = NULL;
777         tmp = WinPriv;
778         WinPriv = WinPriv->next;
779         free(tmp);
780     }
781 
782     dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, NULL);
783 
784     pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
785     ret = (*pScreen->DestroyWindow) (pWin);
786     pScreen->DestroyWindow = KdXVDestroyWindow;
787 
788     return ret;
789 }
790 
791 static void
KdXVWindowExposures(WindowPtr pWin,RegionPtr reg1)792 KdXVWindowExposures(WindowPtr pWin, RegionPtr reg1)
793 {
794     ScreenPtr pScreen = pWin->drawable.pScreen;
795     KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
796     KdXVWindowPtr WinPriv = GET_KDXV_WINDOW(pWin);
797     KdXVWindowPtr pPrev;
798     XvPortRecPrivatePtr pPriv;
799     Bool AreasExposed;
800 
801     AreasExposed = (WinPriv && reg1 && RegionNotEmpty(reg1));
802 
803     pScreen->WindowExposures = ScreenPriv->WindowExposures;
804     (*pScreen->WindowExposures) (pWin, reg1);
805     pScreen->WindowExposures = KdXVWindowExposures;
806 
807     /* filter out XClearWindow/Area */
808     if (!pWin->valdata)
809         return;
810 
811     pPrev = NULL;
812 
813     while (WinPriv) {
814         pPriv = WinPriv->PortRec;
815 
816         /* Reput anyone with a reput function */
817 
818         switch (pPriv->type) {
819         case XvInputMask:
820             KdXVReputVideo(pPriv);
821             break;
822         case XvOutputMask:
823             KdXVRegetVideo(pPriv);
824             break;
825         default:               /* overlaid still/image */
826             if (pPriv->AdaptorRec->ReputImage)
827                 KdXVReputImage(pPriv);
828             else if (AreasExposed) {
829                 KdXVWindowPtr tmp;
830 
831                 if (pPriv->isOn == XV_ON) {
832                     (*pPriv->AdaptorRec->StopVideo) (pPriv->screen,
833                                                      pPriv->DevPriv.ptr, FALSE);
834                     pPriv->isOn = XV_PENDING;
835                 }
836                 pPriv->pDraw = NULL;
837 
838                 if (!pPrev)
839                     dixSetPrivate(&pWin->devPrivates, KdXVWindowKey,
840                                   WinPriv->next);
841                 else
842                     pPrev->next = WinPriv->next;
843                 tmp = WinPriv;
844                 WinPriv = WinPriv->next;
845                 free(tmp);
846                 continue;
847             }
848             break;
849         }
850         pPrev = WinPriv;
851         WinPriv = WinPriv->next;
852     }
853 }
854 
855 static void
KdXVClipNotify(WindowPtr pWin,int dx,int dy)856 KdXVClipNotify(WindowPtr pWin, int dx, int dy)
857 {
858     ScreenPtr pScreen = pWin->drawable.pScreen;
859     KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
860     KdXVWindowPtr WinPriv = GET_KDXV_WINDOW(pWin);
861     KdXVWindowPtr tmp, pPrev = NULL;
862     XvPortRecPrivatePtr pPriv;
863     Bool visible = (pWin->visibility == VisibilityUnobscured) ||
864         (pWin->visibility == VisibilityPartiallyObscured);
865 
866     while (WinPriv) {
867         pPriv = WinPriv->PortRec;
868 
869         if (pPriv->pCompositeClip && pPriv->FreeCompositeClip)
870             RegionDestroy(pPriv->pCompositeClip);
871 
872         pPriv->pCompositeClip = NULL;
873 
874         /* Stop everything except images, but stop them too if the
875            window isn't visible.  But we only remove the images. */
876 
877         if (pPriv->type || !visible) {
878             if (pPriv->isOn == XV_ON) {
879                 (*pPriv->AdaptorRec->StopVideo) (pPriv->screen,
880                                                  pPriv->DevPriv.ptr, FALSE);
881                 pPriv->isOn = XV_PENDING;
882             }
883 
884             if (!pPriv->type) { /* overlaid still/image */
885                 pPriv->pDraw = NULL;
886 
887                 if (!pPrev)
888                     dixSetPrivate(&pWin->devPrivates, KdXVWindowKey,
889                                   WinPriv->next);
890                 else
891                     pPrev->next = WinPriv->next;
892                 tmp = WinPriv;
893                 WinPriv = WinPriv->next;
894                 free(tmp);
895                 continue;
896             }
897         }
898 
899         pPrev = WinPriv;
900         WinPriv = WinPriv->next;
901     }
902 
903     if (ScreenPriv->ClipNotify) {
904         pScreen->ClipNotify = ScreenPriv->ClipNotify;
905         (*pScreen->ClipNotify) (pWin, dx, dy);
906         pScreen->ClipNotify = KdXVClipNotify;
907     }
908 }
909 
910 /**** Required XvScreenRec fields ****/
911 
912 static Bool
KdXVCloseScreen(ScreenPtr pScreen)913 KdXVCloseScreen(ScreenPtr pScreen)
914 {
915     XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
916     KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
917     XvAdaptorPtr pa;
918     int c;
919 
920     if (!ScreenPriv)
921         return TRUE;
922 
923     pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
924     pScreen->WindowExposures = ScreenPriv->WindowExposures;
925     pScreen->ClipNotify = ScreenPriv->ClipNotify;
926     pScreen->CloseScreen = ScreenPriv->CloseScreen;
927 
928 /*   fprintf(stderr,"XV: Unwrapping screen funcs\n"); */
929 
930     for (c = 0, pa = pxvs->pAdaptors; c < pxvs->nAdaptors; c++, pa++) {
931         KdXVFreeAdaptor(pa);
932     }
933 
934     free(pxvs->pAdaptors);
935     free(ScreenPriv);
936 
937     return pScreen->CloseScreen(pScreen);
938 }
939 
940 /**** XvAdaptorRec fields ****/
941 
942 static int
KdXVPutVideo(DrawablePtr pDraw,XvPortPtr pPort,GCPtr pGC,INT16 vid_x,INT16 vid_y,CARD16 vid_w,CARD16 vid_h,INT16 drw_x,INT16 drw_y,CARD16 drw_w,CARD16 drw_h)943 KdXVPutVideo(DrawablePtr pDraw,
944              XvPortPtr pPort,
945              GCPtr pGC,
946              INT16 vid_x, INT16 vid_y,
947              CARD16 vid_w, CARD16 vid_h,
948              INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
949 {
950     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
951 
952     KdScreenPriv(portPriv->screen->pScreen);
953     int result;
954 
955     /* No dumping video to pixmaps... For now anyhow */
956     if (pDraw->type != DRAWABLE_WINDOW) {
957         pPort->pDraw = (DrawablePtr) NULL;
958         return BadAlloc;
959     }
960 
961     /* If we are changing windows, unregister our port in the old window */
962     if (portPriv->pDraw && (portPriv->pDraw != pDraw))
963         KdXVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
964 
965     /* Register our port with the new window */
966     result = KdXVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
967     if (result != Success)
968         return result;
969 
970     portPriv->pDraw = pDraw;
971     portPriv->type = XvInputMask;
972 
973     /* save a copy of these parameters */
974     portPriv->vid_x = vid_x;
975     portPriv->vid_y = vid_y;
976     portPriv->vid_w = vid_w;
977     portPriv->vid_h = vid_h;
978     portPriv->drw_x = drw_x;
979     portPriv->drw_y = drw_y;
980     portPriv->drw_w = drw_w;
981     portPriv->drw_h = drw_h;
982 
983     /* make sure we have the most recent copy of the clientClip */
984     KdXVCopyClip(portPriv, pGC);
985 
986     /* To indicate to the DI layer that we were successful */
987     pPort->pDraw = pDraw;
988 
989     if (!pScreenPriv->enabled)
990         return Success;
991 
992     return (KdXVReputVideo(portPriv));
993 }
994 
995 static int
KdXVPutStill(DrawablePtr pDraw,XvPortPtr pPort,GCPtr pGC,INT16 vid_x,INT16 vid_y,CARD16 vid_w,CARD16 vid_h,INT16 drw_x,INT16 drw_y,CARD16 drw_w,CARD16 drw_h)996 KdXVPutStill(DrawablePtr pDraw,
997              XvPortPtr pPort,
998              GCPtr pGC,
999              INT16 vid_x, INT16 vid_y,
1000              CARD16 vid_w, CARD16 vid_h,
1001              INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
1002 {
1003     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1004     ScreenPtr pScreen = pDraw->pScreen;
1005 
1006     KdScreenPriv(pScreen);
1007     KdScreenInfo *screen = pScreenPriv->screen;
1008     RegionRec WinRegion;
1009     RegionRec ClipRegion;
1010     BoxRec WinBox;
1011     int ret = Success;
1012     Bool clippedAway = FALSE;
1013 
1014     if (pDraw->type != DRAWABLE_WINDOW)
1015         return BadAlloc;
1016 
1017     if (!pScreenPriv->enabled)
1018         return Success;
1019 
1020     WinBox.x1 = pDraw->x + drw_x;
1021     WinBox.y1 = pDraw->y + drw_y;
1022     WinBox.x2 = WinBox.x1 + drw_w;
1023     WinBox.y2 = WinBox.y1 + drw_h;
1024 
1025     RegionInit(&WinRegion, &WinBox, 1);
1026     RegionInit(&ClipRegion, NullBox, 1);
1027     RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
1028 
1029     if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
1030         RegionRec VPReg;
1031         BoxRec VPBox;
1032 
1033         VPBox.x1 = 0;
1034         VPBox.y1 = 0;
1035         VPBox.x2 = screen->width;
1036         VPBox.y2 = screen->height;
1037 
1038         RegionInit(&VPReg, &VPBox, 1);
1039         RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
1040         RegionUninit(&VPReg);
1041     }
1042 
1043     if (portPriv->pDraw) {
1044         KdXVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
1045     }
1046 
1047     if (!RegionNotEmpty(&ClipRegion)) {
1048         clippedAway = TRUE;
1049         goto PUT_STILL_BAILOUT;
1050     }
1051 
1052     ret = (*portPriv->AdaptorRec->PutStill) (portPriv->screen, pDraw,
1053                                              vid_x, vid_y, WinBox.x1, WinBox.y1,
1054                                              vid_w, vid_h, drw_w, drw_h,
1055                                              &ClipRegion,
1056                                              portPriv->DevPriv.ptr);
1057 
1058     if ((ret == Success) &&
1059         (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_STILLS)) {
1060 
1061         KdXVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
1062         portPriv->isOn = XV_ON;
1063         portPriv->pDraw = pDraw;
1064         portPriv->drw_x = drw_x;
1065         portPriv->drw_y = drw_y;
1066         portPriv->drw_w = drw_w;
1067         portPriv->drw_h = drw_h;
1068         portPriv->type = 0;     /* no mask means it's transient and should
1069                                    not be reput once it's removed */
1070         pPort->pDraw = pDraw;   /* make sure we can get stop requests */
1071     }
1072 
1073  PUT_STILL_BAILOUT:
1074 
1075     if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
1076         (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
1077                                             portPriv->DevPriv.ptr, FALSE);
1078         portPriv->isOn = XV_PENDING;
1079     }
1080 
1081     RegionUninit(&WinRegion);
1082     RegionUninit(&ClipRegion);
1083 
1084     return ret;
1085 }
1086 
1087 static int
KdXVGetVideo(DrawablePtr pDraw,XvPortPtr pPort,GCPtr pGC,INT16 vid_x,INT16 vid_y,CARD16 vid_w,CARD16 vid_h,INT16 drw_x,INT16 drw_y,CARD16 drw_w,CARD16 drw_h)1088 KdXVGetVideo(DrawablePtr pDraw,
1089              XvPortPtr pPort,
1090              GCPtr pGC,
1091              INT16 vid_x, INT16 vid_y,
1092              CARD16 vid_w, CARD16 vid_h,
1093              INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
1094 {
1095     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1096     int result;
1097 
1098     KdScreenPriv(portPriv->screen->pScreen);
1099 
1100     /* No pixmaps... For now anyhow */
1101     if (pDraw->type != DRAWABLE_WINDOW) {
1102         pPort->pDraw = (DrawablePtr) NULL;
1103         return BadAlloc;
1104     }
1105 
1106     /* If we are changing windows, unregister our port in the old window */
1107     if (portPriv->pDraw && (portPriv->pDraw != pDraw))
1108         KdXVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
1109 
1110     /* Register our port with the new window */
1111     result = KdXVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
1112     if (result != Success)
1113         return result;
1114 
1115     portPriv->pDraw = pDraw;
1116     portPriv->type = XvOutputMask;
1117 
1118     /* save a copy of these parameters */
1119     portPriv->vid_x = vid_x;
1120     portPriv->vid_y = vid_y;
1121     portPriv->vid_w = vid_w;
1122     portPriv->vid_h = vid_h;
1123     portPriv->drw_x = drw_x;
1124     portPriv->drw_y = drw_y;
1125     portPriv->drw_w = drw_w;
1126     portPriv->drw_h = drw_h;
1127 
1128     /* make sure we have the most recent copy of the clientClip */
1129     KdXVCopyClip(portPriv, pGC);
1130 
1131     /* To indicate to the DI layer that we were successful */
1132     pPort->pDraw = pDraw;
1133 
1134     if (!pScreenPriv->enabled)
1135         return Success;
1136 
1137     return (KdXVRegetVideo(portPriv));
1138 }
1139 
1140 static int
KdXVGetStill(DrawablePtr pDraw,XvPortPtr pPort,GCPtr pGC,INT16 vid_x,INT16 vid_y,CARD16 vid_w,CARD16 vid_h,INT16 drw_x,INT16 drw_y,CARD16 drw_w,CARD16 drw_h)1141 KdXVGetStill(DrawablePtr pDraw,
1142              XvPortPtr pPort,
1143              GCPtr pGC,
1144              INT16 vid_x, INT16 vid_y,
1145              CARD16 vid_w, CARD16 vid_h,
1146              INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
1147 {
1148     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1149     ScreenPtr pScreen = pDraw->pScreen;
1150 
1151     KdScreenPriv(pScreen);
1152     RegionRec WinRegion;
1153     RegionRec ClipRegion;
1154     BoxRec WinBox;
1155     int ret = Success;
1156     Bool clippedAway = FALSE;
1157 
1158     if (pDraw->type != DRAWABLE_WINDOW)
1159         return BadAlloc;
1160 
1161     if (!pScreenPriv->enabled)
1162         return Success;
1163 
1164     WinBox.x1 = pDraw->x + drw_x;
1165     WinBox.y1 = pDraw->y + drw_y;
1166     WinBox.x2 = WinBox.x1 + drw_w;
1167     WinBox.y2 = WinBox.y1 + drw_h;
1168 
1169     RegionInit(&WinRegion, &WinBox, 1);
1170     RegionInit(&ClipRegion, NullBox, 1);
1171     RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
1172 
1173     if (portPriv->pDraw) {
1174         KdXVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
1175     }
1176 
1177     if (!RegionNotEmpty(&ClipRegion)) {
1178         clippedAway = TRUE;
1179         goto GET_STILL_BAILOUT;
1180     }
1181 
1182     ret = (*portPriv->AdaptorRec->GetStill) (portPriv->screen, pDraw,
1183                                              vid_x, vid_y, WinBox.x1, WinBox.y1,
1184                                              vid_w, vid_h, drw_w, drw_h,
1185                                              &ClipRegion,
1186                                              portPriv->DevPriv.ptr);
1187 
1188  GET_STILL_BAILOUT:
1189 
1190     if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
1191         (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
1192                                             portPriv->DevPriv.ptr, FALSE);
1193         portPriv->isOn = XV_PENDING;
1194     }
1195 
1196     RegionUninit(&WinRegion);
1197     RegionUninit(&ClipRegion);
1198 
1199     return ret;
1200 }
1201 
1202 static int
KdXVStopVideo(XvPortPtr pPort,DrawablePtr pDraw)1203 KdXVStopVideo(XvPortPtr pPort, DrawablePtr pDraw)
1204 {
1205     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1206 
1207     KdScreenPriv(portPriv->screen->pScreen);
1208 
1209     if (pDraw->type != DRAWABLE_WINDOW)
1210         return BadAlloc;
1211 
1212     KdXVRemovePortFromWindow((WindowPtr) pDraw, portPriv);
1213 
1214     if (!pScreenPriv->enabled)
1215         return Success;
1216 
1217     /* Must free resources. */
1218 
1219     if (portPriv->isOn > XV_OFF) {
1220         (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
1221                                             portPriv->DevPriv.ptr, TRUE);
1222         portPriv->isOn = XV_OFF;
1223     }
1224 
1225     return Success;
1226 }
1227 
1228 static int
KdXVSetPortAttribute(XvPortPtr pPort,Atom attribute,INT32 value)1229 KdXVSetPortAttribute(XvPortPtr pPort, Atom attribute, INT32 value)
1230 {
1231     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1232 
1233     return ((*portPriv->AdaptorRec->SetPortAttribute) (portPriv->screen,
1234                                                        attribute, value,
1235                                                        portPriv->DevPriv.ptr));
1236 }
1237 
1238 static int
KdXVGetPortAttribute(XvPortPtr pPort,Atom attribute,INT32 * p_value)1239 KdXVGetPortAttribute(XvPortPtr pPort, Atom attribute, INT32 *p_value)
1240 {
1241     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1242 
1243     return ((*portPriv->AdaptorRec->GetPortAttribute) (portPriv->screen,
1244                                                        attribute,
1245                                                        (int *) p_value,
1246                                                        portPriv->DevPriv.ptr));
1247 }
1248 
1249 static int
KdXVQueryBestSize(XvPortPtr pPort,CARD8 motion,CARD16 vid_w,CARD16 vid_h,CARD16 drw_w,CARD16 drw_h,unsigned int * p_w,unsigned int * p_h)1250 KdXVQueryBestSize(XvPortPtr pPort,
1251                   CARD8 motion,
1252                   CARD16 vid_w, CARD16 vid_h,
1253                   CARD16 drw_w, CARD16 drw_h,
1254                   unsigned int *p_w, unsigned int *p_h)
1255 {
1256     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1257 
1258     (*portPriv->AdaptorRec->QueryBestSize) (portPriv->screen,
1259                                             (Bool) motion, vid_w, vid_h, drw_w,
1260                                             drw_h, p_w, p_h,
1261                                             portPriv->DevPriv.ptr);
1262 
1263     return Success;
1264 }
1265 
1266 static int
KdXVPutImage(DrawablePtr pDraw,XvPortPtr pPort,GCPtr pGC,INT16 src_x,INT16 src_y,CARD16 src_w,CARD16 src_h,INT16 drw_x,INT16 drw_y,CARD16 drw_w,CARD16 drw_h,XvImagePtr format,unsigned char * data,Bool sync,CARD16 width,CARD16 height)1267 KdXVPutImage(DrawablePtr pDraw,
1268              XvPortPtr pPort,
1269              GCPtr pGC,
1270              INT16 src_x, INT16 src_y,
1271              CARD16 src_w, CARD16 src_h,
1272              INT16 drw_x, INT16 drw_y,
1273              CARD16 drw_w, CARD16 drw_h,
1274              XvImagePtr format,
1275              unsigned char *data, Bool sync, CARD16 width, CARD16 height)
1276 {
1277     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1278     ScreenPtr pScreen = pDraw->pScreen;
1279 
1280     KdScreenPriv(pScreen);
1281     RegionRec WinRegion;
1282     RegionRec ClipRegion;
1283     BoxRec WinBox;
1284     int ret = Success;
1285     Bool clippedAway = FALSE;
1286 
1287     if (pDraw->type != DRAWABLE_WINDOW)
1288         return BadAlloc;
1289 
1290     if (!pScreenPriv->enabled)
1291         return Success;
1292 
1293     WinBox.x1 = pDraw->x + drw_x;
1294     WinBox.y1 = pDraw->y + drw_y;
1295     WinBox.x2 = WinBox.x1 + drw_w;
1296     WinBox.y2 = WinBox.y1 + drw_h;
1297 
1298     RegionInit(&WinRegion, &WinBox, 1);
1299     RegionInit(&ClipRegion, NullBox, 1);
1300     RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
1301 
1302     if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
1303         RegionRec VPReg;
1304         BoxRec VPBox;
1305 
1306         VPBox.x1 = 0;
1307         VPBox.y1 = 0;
1308         VPBox.x2 = pScreen->width;
1309         VPBox.y2 = pScreen->height;
1310 
1311         RegionInit(&VPReg, &VPBox, 1);
1312         RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
1313         RegionUninit(&VPReg);
1314     }
1315 
1316     if (portPriv->pDraw) {
1317         KdXVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
1318     }
1319 
1320     if (!RegionNotEmpty(&ClipRegion)) {
1321         clippedAway = TRUE;
1322         goto PUT_IMAGE_BAILOUT;
1323     }
1324 
1325     ret = (*portPriv->AdaptorRec->PutImage) (portPriv->screen, pDraw,
1326                                              src_x, src_y, WinBox.x1, WinBox.y1,
1327                                              src_w, src_h, drw_w, drw_h,
1328                                              format->id, data, width, height,
1329                                              sync, &ClipRegion,
1330                                              portPriv->DevPriv.ptr);
1331 
1332     if ((ret == Success) &&
1333         (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_IMAGES)) {
1334 
1335         KdXVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
1336         portPriv->isOn = XV_ON;
1337         portPriv->pDraw = pDraw;
1338         portPriv->drw_x = drw_x;
1339         portPriv->drw_y = drw_y;
1340         portPriv->drw_w = drw_w;
1341         portPriv->drw_h = drw_h;
1342         portPriv->type = 0;     /* no mask means it's transient and should
1343                                    not be reput once it's removed */
1344         pPort->pDraw = pDraw;   /* make sure we can get stop requests */
1345     }
1346 
1347  PUT_IMAGE_BAILOUT:
1348 
1349     if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
1350         (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
1351                                             portPriv->DevPriv.ptr, FALSE);
1352         portPriv->isOn = XV_PENDING;
1353     }
1354 
1355     RegionUninit(&WinRegion);
1356     RegionUninit(&ClipRegion);
1357 
1358     return ret;
1359 }
1360 
1361 static int
KdXVQueryImageAttributes(XvPortPtr pPort,XvImagePtr format,CARD16 * width,CARD16 * height,int * pitches,int * offsets)1362 KdXVQueryImageAttributes(XvPortPtr pPort,
1363                          XvImagePtr format,
1364                          CARD16 *width,
1365                          CARD16 *height, int *pitches, int *offsets)
1366 {
1367     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1368 
1369     return (*portPriv->AdaptorRec->QueryImageAttributes) (portPriv->screen,
1370                                                           format->id, width,
1371                                                           height, pitches,
1372                                                           offsets);
1373 }
1374