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_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
61static int KdXVPutVideo(DrawablePtr, XvPortPtr, GCPtr,
62                        INT16, INT16, CARD16, CARD16,
63                        INT16, INT16, CARD16, CARD16);
64static int KdXVPutStill(DrawablePtr, XvPortPtr, GCPtr,
65                        INT16, INT16, CARD16, CARD16,
66                        INT16, INT16, CARD16, CARD16);
67static int KdXVGetVideo(DrawablePtr, XvPortPtr, GCPtr,
68                        INT16, INT16, CARD16, CARD16,
69                        INT16, INT16, CARD16, CARD16);
70static int KdXVGetStill(DrawablePtr, XvPortPtr, GCPtr,
71                        INT16, INT16, CARD16, CARD16,
72                        INT16, INT16, CARD16, CARD16);
73static int KdXVStopVideo(XvPortPtr, DrawablePtr);
74static int KdXVSetPortAttribute(XvPortPtr, Atom, INT32);
75static int KdXVGetPortAttribute(XvPortPtr, Atom, INT32 *);
76static int KdXVQueryBestSize(XvPortPtr, CARD8,
77                             CARD16, CARD16, CARD16, CARD16,
78                             unsigned int *, unsigned int *);
79static int KdXVPutImage(DrawablePtr, XvPortPtr, GCPtr,
80                        INT16, INT16, CARD16, CARD16,
81                        INT16, INT16, CARD16, CARD16,
82                        XvImagePtr, unsigned char *, Bool, CARD16, CARD16);
83static int KdXVQueryImageAttributes(XvPortPtr, XvImagePtr,
84                                    CARD16 *, CARD16 *, int *, int *);
85
86/* ScreenRec fields */
87
88static Bool KdXVDestroyWindow(WindowPtr pWin);
89static void KdXVWindowExposures(WindowPtr pWin, RegionPtr r1);
90static void KdXVClipNotify(WindowPtr pWin, int dx, int dy);
91static Bool KdXVCloseScreen(ScreenPtr);
92
93/* misc */
94static Bool KdXVInitAdaptors(ScreenPtr, KdVideoAdaptorPtr, int);
95
96static DevPrivateKeyRec KdXVWindowKeyRec;
97
98#define KdXVWindowKey (&KdXVWindowKeyRec)
99static DevPrivateKey KdXvScreenKey;
100static DevPrivateKeyRec KdXVScreenPrivateKey;
101static unsigned long KdXVGeneration = 0;
102static 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
113Bool
114KdXVScreenInit(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
161static void
162KdXVFreeAdaptor(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
185static Bool
186KdXVInitAdaptors(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 its 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
435static void
436KdXVUpdateCompositeClip(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
479static void
480KdXVCopyClip(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
505static int
506KdXVRegetVideo(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
562static int
563KdXVReputVideo(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
638static int
639KdXVReputImage(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
710static int
711KdXVEnlistPortInWindow(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
735static void
736KdXVRemovePortFromWindow(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
759static Bool
760KdXVDestroyWindow(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
791static void
792KdXVWindowExposures(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
855static void
856KdXVClipNotify(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
912static Bool
913KdXVCloseScreen(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
942static int
943KdXVPutVideo(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
995static int
996KdXVPutStill(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
1087static int
1088KdXVGetVideo(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
1140static int
1141KdXVGetStill(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
1202static int
1203KdXVStopVideo(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
1228static int
1229KdXVSetPortAttribute(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
1238static int
1239KdXVGetPortAttribute(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
1249static int
1250KdXVQueryBestSize(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
1266static int
1267KdXVPutImage(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
1361static int
1362KdXVQueryImageAttributes(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