1 /*
2  * XFree86 Xv DDX written by Mark Vojkovich (markv@valinux.com)
3  */
4 /*
5  * Copyright (c) 1998-2003 by The XFree86 Project, Inc.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23  * OTHER DEALINGS IN THE SOFTWARE.
24  *
25  * Except as contained in this notice, the name of the copyright holder(s)
26  * and author(s) shall not be used in advertising or otherwise to promote
27  * the sale, use or other dealings in this Software without prior written
28  * authorization from the copyright holder(s) and author(s).
29  */
30 
31 #ifdef HAVE_XORG_CONFIG_H
32 #include <xorg-config.h>
33 #endif
34 
35 #include "misc.h"
36 #include "xf86.h"
37 #include "xf86_OSproc.h"
38 
39 #include <X11/X.h>
40 #include <X11/Xproto.h>
41 #include "scrnintstr.h"
42 #include "regionstr.h"
43 #include "windowstr.h"
44 #include "pixmapstr.h"
45 #include "mivalidate.h"
46 #include "validate.h"
47 #include "resource.h"
48 #include "gcstruct.h"
49 #include "dixstruct.h"
50 
51 #include <X11/extensions/Xv.h>
52 #include <X11/extensions/Xvproto.h>
53 #include "xvdix.h"
54 
55 #include "xf86xvpriv.h"
56 
57 /* XvAdaptorRec fields */
58 
59 static int xf86XVPutVideo(DrawablePtr, XvPortPtr, GCPtr,
60                           INT16, INT16, CARD16, CARD16,
61                           INT16, INT16, CARD16, CARD16);
62 static int xf86XVPutStill(DrawablePtr, XvPortPtr, GCPtr,
63                           INT16, INT16, CARD16, CARD16,
64                           INT16, INT16, CARD16, CARD16);
65 static int xf86XVGetVideo(DrawablePtr, XvPortPtr, GCPtr,
66                           INT16, INT16, CARD16, CARD16,
67                           INT16, INT16, CARD16, CARD16);
68 static int xf86XVGetStill(DrawablePtr, XvPortPtr, GCPtr,
69                           INT16, INT16, CARD16, CARD16,
70                           INT16, INT16, CARD16, CARD16);
71 static int xf86XVStopVideo(XvPortPtr, DrawablePtr);
72 static int xf86XVSetPortAttribute(XvPortPtr, Atom, INT32);
73 static int xf86XVGetPortAttribute(XvPortPtr, Atom, INT32 *);
74 static int xf86XVQueryBestSize(XvPortPtr, CARD8,
75                                CARD16, CARD16, CARD16, CARD16,
76                                unsigned int *, unsigned int *);
77 static int xf86XVPutImage(DrawablePtr, XvPortPtr, GCPtr,
78                           INT16, INT16, CARD16, CARD16,
79                           INT16, INT16, CARD16, CARD16,
80                           XvImagePtr, unsigned char *, Bool, CARD16, CARD16);
81 static int xf86XVQueryImageAttributes(XvPortPtr, XvImagePtr,
82                                       CARD16 *, CARD16 *, int *, int *);
83 
84 /* ScreenRec fields */
85 
86 static Bool xf86XVDestroyWindow(WindowPtr pWin);
87 static void xf86XVWindowExposures(WindowPtr pWin, RegionPtr r1);
88 static void xf86XVPostValidateTree(WindowPtr pWin, WindowPtr pLayerWin,
89                                    VTKind kind);
90 static void xf86XVClipNotify(WindowPtr pWin, int dx, int dy);
91 static Bool xf86XVCloseScreen(ScreenPtr);
92 
93 #define PostValidateTreeUndefined ((PostValidateTreeProcPtr)-1)
94 
95 /* ScrnInfoRec functions */
96 
97 static Bool xf86XVEnterVT(ScrnInfoPtr);
98 static void xf86XVLeaveVT(ScrnInfoPtr);
99 static void xf86XVAdjustFrame(ScrnInfoPtr, int x, int y);
100 static void xf86XVModeSet(ScrnInfoPtr pScrn);
101 
102 /* misc */
103 
104 static Bool xf86XVInitAdaptors(ScreenPtr, XF86VideoAdaptorPtr *, int);
105 
106 static DevPrivateKeyRec XF86XVWindowKeyRec;
107 
108 #define XF86XVWindowKey (&XF86XVWindowKeyRec)
109 
110 /* dixmain.c XvScreenPtr screen private */
111 DevPrivateKey XF86XvScreenKey;
112 /** xf86xv.c XF86XVScreenPtr screen private */
113 static DevPrivateKeyRec XF86XVScreenPrivateKey;
114 
115 static unsigned long PortResource = 0;
116 
117 #define GET_XV_SCREEN(pScreen) \
118     ((XvScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, XF86XvScreenKey))
119 
120 #define GET_XF86XV_SCREEN(pScreen) \
121     ((XF86XVScreenPtr)(dixGetPrivate(&pScreen->devPrivates, &XF86XVScreenPrivateKey)))
122 
123 #define GET_XF86XV_WINDOW(pWin) \
124     ((XF86XVWindowPtr)dixLookupPrivate(&(pWin)->devPrivates, XF86XVWindowKey))
125 
126 static xf86XVInitGenericAdaptorPtr *GenDrivers = NULL;
127 static int NumGenDrivers = 0;
128 
129 int
xf86XVRegisterGenericAdaptorDriver(xf86XVInitGenericAdaptorPtr InitFunc)130 xf86XVRegisterGenericAdaptorDriver(xf86XVInitGenericAdaptorPtr InitFunc)
131 {
132     xf86XVInitGenericAdaptorPtr *newdrivers;
133 
134     newdrivers = reallocarray(GenDrivers, 1 + NumGenDrivers,
135                               sizeof(xf86XVInitGenericAdaptorPtr));
136     if (!newdrivers)
137         return 0;
138     GenDrivers = newdrivers;
139 
140     GenDrivers[NumGenDrivers++] = InitFunc;
141 
142     return 1;
143 }
144 
145 int
xf86XVListGenericAdaptors(ScrnInfoPtr pScrn,XF86VideoAdaptorPtr ** adaptors)146 xf86XVListGenericAdaptors(ScrnInfoPtr pScrn, XF86VideoAdaptorPtr ** adaptors)
147 {
148     int i, j, n, num;
149     XF86VideoAdaptorPtr *DrivAdap, *new;
150 
151     num = 0;
152     *adaptors = NULL;
153     /*
154      * The v4l driver registers itself first, but can use surfaces registered
155      * by other drivers.  So, call the v4l driver last.
156      */
157     for (i = NumGenDrivers; --i >= 0;) {
158         DrivAdap = NULL;
159         n = (*GenDrivers[i]) (pScrn, &DrivAdap);
160         if (0 == n)
161             continue;
162         new = reallocarray(*adaptors, num + n, sizeof(XF86VideoAdaptorPtr));
163         if (NULL == new)
164             continue;
165         *adaptors = new;
166         for (j = 0; j < n; j++, num++)
167             (*adaptors)[num] = DrivAdap[j];
168     }
169     return num;
170 }
171 
172 /****************  Offscreen surface stuff *******************/
173 
174 typedef struct {
175     XF86OffscreenImagePtr images;
176     int num;
177 } OffscreenImageRec;
178 
179 static DevPrivateKeyRec OffscreenPrivateKeyRec;
180 
181 #define OffscreenPrivateKey (&OffscreenPrivateKeyRec)
182 #define GetOffscreenImage(pScreen) ((OffscreenImageRec *) dixLookupPrivate(&(pScreen)->devPrivates, OffscreenPrivateKey))
183 
184 Bool
xf86XVRegisterOffscreenImages(ScreenPtr pScreen,XF86OffscreenImagePtr images,int num)185 xf86XVRegisterOffscreenImages(ScreenPtr pScreen,
186                               XF86OffscreenImagePtr images, int num)
187 {
188     OffscreenImageRec *OffscreenImage;
189 
190     /* This function may be called before xf86XVScreenInit, so there's
191      * no better place than this to call dixRegisterPrivateKey to ensure we
192      * have space reserved. After the first call it is a no-op. */
193     if (!dixRegisterPrivateKey
194         (OffscreenPrivateKey, PRIVATE_SCREEN, sizeof(OffscreenImageRec)) ||
195         !(OffscreenImage = GetOffscreenImage(pScreen)))
196         /* Every X.org driver assumes this function always succeeds, so
197          * just die on allocation failure. */
198         FatalError
199             ("Could not allocate private storage for XV offscreen images.\n");
200 
201     OffscreenImage->num = num;
202     OffscreenImage->images = images;
203     return TRUE;
204 }
205 
206 XF86OffscreenImagePtr
xf86XVQueryOffscreenImages(ScreenPtr pScreen,int * num)207 xf86XVQueryOffscreenImages(ScreenPtr pScreen, int *num)
208 {
209     OffscreenImageRec *OffscreenImage = GetOffscreenImage(pScreen);
210 
211     *num = OffscreenImage->num;
212     return OffscreenImage->images;
213 }
214 
215 XF86VideoAdaptorPtr
xf86XVAllocateVideoAdaptorRec(ScrnInfoPtr pScrn)216 xf86XVAllocateVideoAdaptorRec(ScrnInfoPtr pScrn)
217 {
218     return calloc(1, sizeof(XF86VideoAdaptorRec));
219 }
220 
221 void
xf86XVFreeVideoAdaptorRec(XF86VideoAdaptorPtr ptr)222 xf86XVFreeVideoAdaptorRec(XF86VideoAdaptorPtr ptr)
223 {
224     free(ptr);
225 }
226 
227 Bool
xf86XVScreenInit(ScreenPtr pScreen,XF86VideoAdaptorPtr * adaptors,int num)228 xf86XVScreenInit(ScreenPtr pScreen, XF86VideoAdaptorPtr * adaptors, int num)
229 {
230     ScrnInfoPtr pScrn;
231     XF86XVScreenPtr ScreenPriv;
232 
233     if (num <= 0 || noXvExtension)
234         return FALSE;
235 
236     if (Success != XvScreenInit(pScreen))
237         return FALSE;
238 
239     if (!dixRegisterPrivateKey(&XF86XVWindowKeyRec, PRIVATE_WINDOW, 0))
240         return FALSE;
241     if (!dixRegisterPrivateKey(&XF86XVScreenPrivateKey, PRIVATE_SCREEN, 0))
242         return FALSE;
243 
244     XF86XvScreenKey = XvGetScreenKey();
245 
246     PortResource = XvGetRTPort();
247 
248     ScreenPriv = malloc(sizeof(XF86XVScreenRec));
249     dixSetPrivate(&pScreen->devPrivates, &XF86XVScreenPrivateKey, ScreenPriv);
250 
251     if (!ScreenPriv)
252         return FALSE;
253 
254     pScrn = xf86ScreenToScrn(pScreen);
255 
256     ScreenPriv->DestroyWindow = pScreen->DestroyWindow;
257     ScreenPriv->WindowExposures = pScreen->WindowExposures;
258     ScreenPriv->PostValidateTree = PostValidateTreeUndefined;
259     ScreenPriv->ClipNotify = pScreen->ClipNotify;
260     ScreenPriv->CloseScreen = pScreen->CloseScreen;
261     ScreenPriv->EnterVT = pScrn->EnterVT;
262     ScreenPriv->LeaveVT = pScrn->LeaveVT;
263     ScreenPriv->AdjustFrame = pScrn->AdjustFrame;
264     ScreenPriv->ModeSet = pScrn->ModeSet;
265 
266     pScreen->DestroyWindow = xf86XVDestroyWindow;
267     pScreen->WindowExposures = xf86XVWindowExposures;
268     pScreen->ClipNotify = xf86XVClipNotify;
269     pScreen->CloseScreen = xf86XVCloseScreen;
270     pScrn->EnterVT = xf86XVEnterVT;
271     pScrn->LeaveVT = xf86XVLeaveVT;
272     if (pScrn->AdjustFrame)
273         pScrn->AdjustFrame = xf86XVAdjustFrame;
274     pScrn->ModeSet = xf86XVModeSet;
275 
276     if (!xf86XVInitAdaptors(pScreen, adaptors, num))
277         return FALSE;
278 
279     return TRUE;
280 }
281 
282 static void
xf86XVFreeAdaptor(XvAdaptorPtr pAdaptor)283 xf86XVFreeAdaptor(XvAdaptorPtr pAdaptor)
284 {
285     int i;
286 
287     if (pAdaptor->pPorts) {
288         XvPortPtr pPort = pAdaptor->pPorts;
289         XvPortRecPrivatePtr pPriv;
290 
291         for (i = 0; i < pAdaptor->nPorts; i++, pPort++) {
292             pPriv = (XvPortRecPrivatePtr) pPort->devPriv.ptr;
293             if (pPriv) {
294                 if (pPriv->clientClip)
295                     RegionDestroy(pPriv->clientClip);
296                 if (pPriv->pCompositeClip && pPriv->FreeCompositeClip)
297                     RegionDestroy(pPriv->pCompositeClip);
298                 if (pPriv->ckeyFilled)
299                     RegionDestroy(pPriv->ckeyFilled);
300                 free(pPriv);
301             }
302         }
303     }
304 
305     XvFreeAdaptor(pAdaptor);
306 }
307 
308 static Bool
xf86XVInitAdaptors(ScreenPtr pScreen,XF86VideoAdaptorPtr * infoPtr,int number)309 xf86XVInitAdaptors(ScreenPtr pScreen, XF86VideoAdaptorPtr * infoPtr, int number)
310 {
311     XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
312     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
313     XF86VideoAdaptorPtr adaptorPtr;
314     XvAdaptorPtr pAdaptor, pa;
315     XvAdaptorRecPrivatePtr adaptorPriv;
316     int na, numAdaptor;
317     XvPortRecPrivatePtr portPriv;
318     XvPortPtr pPort, pp;
319     int numPort;
320     XF86VideoFormatPtr formatPtr;
321     XvFormatPtr pFormat, pf;
322     int numFormat, totFormat;
323     XF86VideoEncodingPtr encodingPtr;
324     XvEncodingPtr pEncode, pe;
325     int numVisuals;
326     VisualPtr pVisual;
327     int i;
328 
329     pxvs->nAdaptors = 0;
330     pxvs->pAdaptors = NULL;
331 
332     if (!(pAdaptor = calloc(number, sizeof(XvAdaptorRec))))
333         return FALSE;
334 
335     for (pa = pAdaptor, na = 0, numAdaptor = 0; na < number; na++, adaptorPtr++) {
336         adaptorPtr = infoPtr[na];
337 
338         if (!adaptorPtr->StopVideo || !adaptorPtr->SetPortAttribute ||
339             !adaptorPtr->GetPortAttribute || !adaptorPtr->QueryBestSize)
340             continue;
341 
342         /* client libs expect at least one encoding */
343         if (!adaptorPtr->nEncodings || !adaptorPtr->pEncodings)
344             continue;
345 
346         pa->type = adaptorPtr->type;
347 
348         if (!adaptorPtr->PutVideo && !adaptorPtr->GetVideo)
349             pa->type &= ~XvVideoMask;
350 
351         if (!adaptorPtr->PutStill && !adaptorPtr->GetStill)
352             pa->type &= ~XvStillMask;
353 
354         if (!adaptorPtr->PutImage || !adaptorPtr->QueryImageAttributes)
355             pa->type &= ~XvImageMask;
356 
357         if (!adaptorPtr->PutVideo && !adaptorPtr->PutImage &&
358             !adaptorPtr->PutStill)
359             pa->type &= ~XvInputMask;
360 
361         if (!adaptorPtr->GetVideo && !adaptorPtr->GetStill)
362             pa->type &= ~XvOutputMask;
363 
364         if (!(adaptorPtr->type & (XvPixmapMask | XvWindowMask)))
365             continue;
366         if (!(adaptorPtr->type & (XvImageMask | XvVideoMask | XvStillMask)))
367             continue;
368 
369         pa->pScreen = pScreen;
370         pa->ddPutVideo = xf86XVPutVideo;
371         pa->ddPutStill = xf86XVPutStill;
372         pa->ddGetVideo = xf86XVGetVideo;
373         pa->ddGetStill = xf86XVGetStill;
374         pa->ddStopVideo = xf86XVStopVideo;
375         pa->ddPutImage = xf86XVPutImage;
376         pa->ddSetPortAttribute = xf86XVSetPortAttribute;
377         pa->ddGetPortAttribute = xf86XVGetPortAttribute;
378         pa->ddQueryBestSize = xf86XVQueryBestSize;
379         pa->ddQueryImageAttributes = xf86XVQueryImageAttributes;
380         pa->name = strdup(adaptorPtr->name);
381 
382         if (adaptorPtr->nEncodings &&
383             (pEncode = calloc(adaptorPtr->nEncodings, sizeof(XvEncodingRec)))) {
384 
385             for (pe = pEncode, encodingPtr = adaptorPtr->pEncodings, i = 0;
386                  i < adaptorPtr->nEncodings; pe++, i++, encodingPtr++) {
387                 pe->id = encodingPtr->id;
388                 pe->pScreen = pScreen;
389                 pe->name = strdup(encodingPtr->name);
390                 pe->width = encodingPtr->width;
391                 pe->height = encodingPtr->height;
392                 pe->rate.numerator = encodingPtr->rate.numerator;
393                 pe->rate.denominator = encodingPtr->rate.denominator;
394             }
395             pa->nEncodings = adaptorPtr->nEncodings;
396             pa->pEncodings = pEncode;
397         }
398 
399         if (adaptorPtr->nImages &&
400             (pa->pImages = calloc(adaptorPtr->nImages, sizeof(XvImageRec)))) {
401             memcpy(pa->pImages, adaptorPtr->pImages,
402                    adaptorPtr->nImages * sizeof(XvImageRec));
403             pa->nImages = adaptorPtr->nImages;
404         }
405 
406         if (adaptorPtr->nAttributes &&
407             (pa->pAttributes = calloc(adaptorPtr->nAttributes,
408                                       sizeof(XvAttributeRec)))) {
409             memcpy(pa->pAttributes, adaptorPtr->pAttributes,
410                    adaptorPtr->nAttributes * sizeof(XvAttributeRec));
411 
412             for (i = 0; i < adaptorPtr->nAttributes; i++) {
413                 pa->pAttributes[i].name =
414                     strdup(adaptorPtr->pAttributes[i].name);
415             }
416 
417             pa->nAttributes = adaptorPtr->nAttributes;
418         }
419 
420         totFormat = adaptorPtr->nFormats;
421 
422         if (!(pFormat = calloc(totFormat, sizeof(XvFormatRec)))) {
423             xf86XVFreeAdaptor(pa);
424             continue;
425         }
426         for (pf = pFormat, i = 0, numFormat = 0, formatPtr =
427              adaptorPtr->pFormats; i < adaptorPtr->nFormats; i++, formatPtr++) {
428             numVisuals = pScreen->numVisuals;
429             pVisual = pScreen->visuals;
430 
431             while (numVisuals--) {
432                 if ((pVisual->class == formatPtr->class) &&
433                     (pVisual->nplanes == formatPtr->depth)) {
434 
435                     if (numFormat >= totFormat) {
436                         void *moreSpace;
437 
438                         totFormat *= 2;
439                         moreSpace = reallocarray(pFormat, totFormat,
440                                                  sizeof(XvFormatRec));
441                         if (!moreSpace)
442                             break;
443                         pFormat = moreSpace;
444                         pf = pFormat + numFormat;
445                     }
446 
447                     pf->visual = pVisual->vid;
448                     pf->depth = formatPtr->depth;
449 
450                     pf++;
451                     numFormat++;
452                 }
453                 pVisual++;
454             }
455         }
456         pa->nFormats = numFormat;
457         pa->pFormats = pFormat;
458         if (!numFormat) {
459             xf86XVFreeAdaptor(pa);
460             continue;
461         }
462 
463         if (!(adaptorPriv = calloc(1, sizeof(XvAdaptorRecPrivate)))) {
464             xf86XVFreeAdaptor(pa);
465             continue;
466         }
467 
468         adaptorPriv->flags = adaptorPtr->flags;
469         adaptorPriv->PutVideo = adaptorPtr->PutVideo;
470         adaptorPriv->PutStill = adaptorPtr->PutStill;
471         adaptorPriv->GetVideo = adaptorPtr->GetVideo;
472         adaptorPriv->GetStill = adaptorPtr->GetStill;
473         adaptorPriv->StopVideo = adaptorPtr->StopVideo;
474         adaptorPriv->SetPortAttribute = adaptorPtr->SetPortAttribute;
475         adaptorPriv->GetPortAttribute = adaptorPtr->GetPortAttribute;
476         adaptorPriv->QueryBestSize = adaptorPtr->QueryBestSize;
477         adaptorPriv->QueryImageAttributes = adaptorPtr->QueryImageAttributes;
478         adaptorPriv->PutImage = adaptorPtr->PutImage;
479         adaptorPriv->ReputImage = adaptorPtr->ReputImage;       /* image/still */
480 
481         pa->devPriv.ptr = (void *) adaptorPriv;
482 
483         if (!(pPort = calloc(adaptorPtr->nPorts, sizeof(XvPortRec)))) {
484             xf86XVFreeAdaptor(pa);
485             continue;
486         }
487         for (pp = pPort, i = 0, numPort = 0; i < adaptorPtr->nPorts; i++) {
488 
489             if (!(pp->id = FakeClientID(0)))
490                 continue;
491 
492             if (!(portPriv = calloc(1, sizeof(XvPortRecPrivate))))
493                 continue;
494 
495             if (!AddResource(pp->id, PortResource, pp)) {
496                 free(portPriv);
497                 continue;
498             }
499 
500             pp->pAdaptor = pa;
501             pp->pNotify = (XvPortNotifyPtr) NULL;
502             pp->pDraw = (DrawablePtr) NULL;
503             pp->client = (ClientPtr) NULL;
504             pp->grab.client = (ClientPtr) NULL;
505             pp->time = currentTime;
506             pp->devPriv.ptr = portPriv;
507 
508             portPriv->pScrn = pScrn;
509             portPriv->AdaptorRec = adaptorPriv;
510             portPriv->DevPriv.ptr = adaptorPtr->pPortPrivates[i].ptr;
511 
512             pp++;
513             numPort++;
514         }
515         pa->nPorts = numPort;
516         pa->pPorts = pPort;
517         if (!numPort) {
518             xf86XVFreeAdaptor(pa);
519             continue;
520         }
521 
522         pa->base_id = pPort->id;
523 
524         pa++;
525         numAdaptor++;
526     }
527 
528     if (numAdaptor) {
529         pxvs->nAdaptors = numAdaptor;
530         pxvs->pAdaptors = pAdaptor;
531     }
532     else {
533         free(pAdaptor);
534         return FALSE;
535     }
536 
537     return TRUE;
538 }
539 
540 /* Video should be clipped to the intersection of the window cliplist
541    and the client cliplist specified in the GC for which the video was
542    initialized.  When we need to reclip a window, the GC that started
543    the video may not even be around anymore.  That's why we save the
544    client clip from the GC when the video is initialized.  We then
545    use xf86XVUpdateCompositeClip to calculate the new composite clip
546    when we need it.  This is different from what DEC did.  They saved
547    the GC and used its clip list when they needed to reclip the window,
548    even if the client clip was different from the one the video was
549    initialized with.  If the original GC was destroyed, they had to stop
550    the video.  I like the new method better (MArk).
551 
552    This function only works for windows.  Will need to rewrite when
553    (if) we support pixmap rendering.
554 */
555 
556 static void
xf86XVUpdateCompositeClip(XvPortRecPrivatePtr portPriv)557 xf86XVUpdateCompositeClip(XvPortRecPrivatePtr portPriv)
558 {
559     RegionPtr pregWin, pCompositeClip;
560     WindowPtr pWin;
561     Bool freeCompClip = FALSE;
562 
563     if (portPriv->pCompositeClip)
564         return;
565 
566     pWin = (WindowPtr) portPriv->pDraw;
567 
568     /* get window clip list */
569     if (portPriv->subWindowMode == IncludeInferiors) {
570         pregWin = NotClippedByChildren(pWin);
571         freeCompClip = TRUE;
572     }
573     else
574         pregWin = &pWin->clipList;
575 
576     if (!portPriv->clientClip) {
577         portPriv->pCompositeClip = pregWin;
578         portPriv->FreeCompositeClip = freeCompClip;
579         return;
580     }
581 
582     pCompositeClip = RegionCreate(NullBox, 1);
583     RegionCopy(pCompositeClip, portPriv->clientClip);
584     RegionTranslate(pCompositeClip, portPriv->pDraw->x, portPriv->pDraw->y);
585     RegionIntersect(pCompositeClip, pregWin, pCompositeClip);
586 
587     portPriv->pCompositeClip = pCompositeClip;
588     portPriv->FreeCompositeClip = TRUE;
589 
590     if (freeCompClip) {
591         RegionDestroy(pregWin);
592     }
593 }
594 
595 /* Save the current clientClip and update the CompositeClip whenever
596    we have a fresh GC */
597 
598 static void
xf86XVCopyClip(XvPortRecPrivatePtr portPriv,GCPtr pGC)599 xf86XVCopyClip(XvPortRecPrivatePtr portPriv, GCPtr pGC)
600 {
601     /* copy the new clip if it exists */
602     if (pGC->clientClip) {
603         if (!portPriv->clientClip)
604             portPriv->clientClip = RegionCreate(NullBox, 1);
605         /* Note: this is in window coordinates */
606         RegionCopy(portPriv->clientClip, pGC->clientClip);
607         RegionTranslate(portPriv->clientClip, pGC->clipOrg.x, pGC->clipOrg.y);
608     }
609     else if (portPriv->clientClip) {    /* free the old clientClip */
610         RegionDestroy(portPriv->clientClip);
611         portPriv->clientClip = NULL;
612     }
613 
614     /* get rid of the old clip list */
615     if (portPriv->pCompositeClip && portPriv->FreeCompositeClip) {
616         RegionDestroy(portPriv->pCompositeClip);
617     }
618 
619     portPriv->pCompositeClip = pGC->pCompositeClip;
620     portPriv->FreeCompositeClip = FALSE;
621     portPriv->subWindowMode = pGC->subWindowMode;
622 }
623 
624 static void
xf86XVCopyCompositeClip(XvPortRecPrivatePtr portPriv,GCPtr pGC,DrawablePtr pDraw)625 xf86XVCopyCompositeClip(XvPortRecPrivatePtr portPriv,
626                         GCPtr pGC, DrawablePtr pDraw)
627 {
628     if (!portPriv->clientClip)
629         portPriv->clientClip = RegionCreate(NullBox, 1);
630     /* Keep the original GC composite clip around for ReputImage */
631     RegionCopy(portPriv->clientClip, pGC->pCompositeClip);
632     RegionTranslate(portPriv->clientClip, -pDraw->x, -pDraw->y);
633 
634     /* get rid of the old clip list */
635     if (portPriv->pCompositeClip && portPriv->FreeCompositeClip)
636         RegionDestroy(portPriv->pCompositeClip);
637 
638     portPriv->pCompositeClip = pGC->pCompositeClip;
639     portPriv->FreeCompositeClip = FALSE;
640     portPriv->subWindowMode = pGC->subWindowMode;
641 }
642 
643 static int
xf86XVRegetVideo(XvPortRecPrivatePtr portPriv)644 xf86XVRegetVideo(XvPortRecPrivatePtr portPriv)
645 {
646     RegionRec WinRegion;
647     RegionRec ClipRegion;
648     BoxRec WinBox;
649     int ret = Success;
650     Bool clippedAway = FALSE;
651 
652     xf86XVUpdateCompositeClip(portPriv);
653 
654     /* translate the video region to the screen */
655     WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
656     WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
657     WinBox.x2 = WinBox.x1 + portPriv->drw_w;
658     WinBox.y2 = WinBox.y1 + portPriv->drw_h;
659 
660     /* clip to the window composite clip */
661     RegionInit(&WinRegion, &WinBox, 1);
662     RegionNull(&ClipRegion);
663     RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
664 
665     /* that's all if it's totally obscured */
666     if (!RegionNotEmpty(&ClipRegion)) {
667         clippedAway = TRUE;
668         goto CLIP_VIDEO_BAILOUT;
669     }
670 
671     ret = (*portPriv->AdaptorRec->GetVideo) (portPriv->pScrn,
672                                              portPriv->vid_x, portPriv->vid_y,
673                                              WinBox.x1, WinBox.y1,
674                                              portPriv->vid_w, portPriv->vid_h,
675                                              portPriv->drw_w, portPriv->drw_h,
676                                              &ClipRegion, portPriv->DevPriv.ptr,
677                                              portPriv->pDraw);
678 
679     if (ret == Success)
680         portPriv->isOn = XV_ON;
681 
682  CLIP_VIDEO_BAILOUT:
683 
684     if ((clippedAway || (ret != Success)) && portPriv->isOn == XV_ON) {
685         (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
686                                             portPriv->DevPriv.ptr, FALSE);
687         portPriv->isOn = XV_PENDING;
688     }
689 
690     /* This clip was copied and only good for one shot */
691     if (!portPriv->FreeCompositeClip)
692         portPriv->pCompositeClip = NULL;
693 
694     RegionUninit(&WinRegion);
695     RegionUninit(&ClipRegion);
696 
697     return ret;
698 }
699 
700 static int
xf86XVReputVideo(XvPortRecPrivatePtr portPriv)701 xf86XVReputVideo(XvPortRecPrivatePtr portPriv)
702 {
703     RegionRec WinRegion;
704     RegionRec ClipRegion;
705     BoxRec WinBox;
706     int ret = Success;
707     Bool clippedAway = FALSE;
708 
709     xf86XVUpdateCompositeClip(portPriv);
710 
711     /* translate the video region to the screen */
712     WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
713     WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
714     WinBox.x2 = WinBox.x1 + portPriv->drw_w;
715     WinBox.y2 = WinBox.y1 + portPriv->drw_h;
716 
717     /* clip to the window composite clip */
718     RegionInit(&WinRegion, &WinBox, 1);
719     RegionNull(&ClipRegion);
720     RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
721 
722     /* clip and translate to the viewport */
723     if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
724         RegionRec VPReg;
725         BoxRec VPBox;
726 
727         VPBox.x1 = portPriv->pScrn->frameX0;
728         VPBox.y1 = portPriv->pScrn->frameY0;
729         VPBox.x2 = portPriv->pScrn->frameX1 + 1;
730         VPBox.y2 = portPriv->pScrn->frameY1 + 1;
731 
732         RegionInit(&VPReg, &VPBox, 1);
733         RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
734         RegionUninit(&VPReg);
735     }
736 
737     /* that's all if it's totally obscured */
738     if (!RegionNotEmpty(&ClipRegion)) {
739         clippedAway = TRUE;
740         goto CLIP_VIDEO_BAILOUT;
741     }
742 
743     ret = (*portPriv->AdaptorRec->PutVideo) (portPriv->pScrn,
744                                              portPriv->vid_x, portPriv->vid_y,
745                                              WinBox.x1, WinBox.y1,
746                                              portPriv->vid_w, portPriv->vid_h,
747                                              portPriv->drw_w, portPriv->drw_h,
748                                              &ClipRegion, portPriv->DevPriv.ptr,
749                                              portPriv->pDraw);
750 
751     if (ret == Success)
752         portPriv->isOn = XV_ON;
753 
754  CLIP_VIDEO_BAILOUT:
755 
756     if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
757         (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
758                                             portPriv->DevPriv.ptr, FALSE);
759         portPriv->isOn = XV_PENDING;
760     }
761 
762     /* This clip was copied and only good for one shot */
763     if (!portPriv->FreeCompositeClip)
764         portPriv->pCompositeClip = NULL;
765 
766     RegionUninit(&WinRegion);
767     RegionUninit(&ClipRegion);
768 
769     return ret;
770 }
771 
772 /* Reput image/still */
773 static int
xf86XVReputImage(XvPortRecPrivatePtr portPriv)774 xf86XVReputImage(XvPortRecPrivatePtr portPriv)
775 {
776     RegionRec WinRegion;
777     RegionRec ClipRegion;
778     BoxRec WinBox;
779     int ret = Success;
780     Bool clippedAway = FALSE;
781 
782     xf86XVUpdateCompositeClip(portPriv);
783 
784     /* the clip can get smaller over time */
785     RegionCopy(portPriv->clientClip, portPriv->pCompositeClip);
786     RegionTranslate(portPriv->clientClip,
787                     -portPriv->pDraw->x, -portPriv->pDraw->y);
788 
789     /* translate the video region to the screen */
790     WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
791     WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
792     WinBox.x2 = WinBox.x1 + portPriv->drw_w;
793     WinBox.y2 = WinBox.y1 + portPriv->drw_h;
794 
795     /* clip to the window composite clip */
796     RegionInit(&WinRegion, &WinBox, 1);
797     RegionNull(&ClipRegion);
798     RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
799 
800     /* clip and translate to the viewport */
801     if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
802         RegionRec VPReg;
803         BoxRec VPBox;
804 
805         VPBox.x1 = portPriv->pScrn->frameX0;
806         VPBox.y1 = portPriv->pScrn->frameY0;
807         VPBox.x2 = portPriv->pScrn->frameX1 + 1;
808         VPBox.y2 = portPriv->pScrn->frameY1 + 1;
809 
810         RegionInit(&VPReg, &VPBox, 1);
811         RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
812         RegionUninit(&VPReg);
813     }
814 
815     /* that's all if it's totally obscured */
816     if (!RegionNotEmpty(&ClipRegion)) {
817         clippedAway = TRUE;
818         goto CLIP_VIDEO_BAILOUT;
819     }
820 
821     ret = (*portPriv->AdaptorRec->ReputImage) (portPriv->pScrn,
822                                                portPriv->vid_x, portPriv->vid_y,
823                                                WinBox.x1, WinBox.y1,
824                                                portPriv->vid_w, portPriv->vid_h,
825                                                portPriv->drw_w, portPriv->drw_h,
826                                                &ClipRegion,
827                                                portPriv->DevPriv.ptr,
828                                                portPriv->pDraw);
829 
830     portPriv->isOn = (ret == Success) ? XV_ON : XV_OFF;
831 
832  CLIP_VIDEO_BAILOUT:
833 
834     if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
835         (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
836                                             portPriv->DevPriv.ptr, FALSE);
837         portPriv->isOn = XV_PENDING;
838     }
839 
840     /* This clip was copied and only good for one shot */
841     if (!portPriv->FreeCompositeClip)
842         portPriv->pCompositeClip = NULL;
843 
844     RegionUninit(&WinRegion);
845     RegionUninit(&ClipRegion);
846 
847     return ret;
848 }
849 
850 static int
xf86XVReputAllVideo(WindowPtr pWin,void * data)851 xf86XVReputAllVideo(WindowPtr pWin, void *data)
852 {
853     XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
854 
855     while (WinPriv) {
856         if (WinPriv->PortRec->type == XvInputMask)
857             xf86XVReputVideo(WinPriv->PortRec);
858         else
859             xf86XVRegetVideo(WinPriv->PortRec);
860         WinPriv = WinPriv->next;
861     }
862 
863     return WT_WALKCHILDREN;
864 }
865 
866 static int
xf86XVEnlistPortInWindow(WindowPtr pWin,XvPortRecPrivatePtr portPriv)867 xf86XVEnlistPortInWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
868 {
869     XF86XVWindowPtr winPriv, PrivRoot;
870 
871     winPriv = PrivRoot = GET_XF86XV_WINDOW(pWin);
872 
873     /* Enlist our port in the window private */
874     while (winPriv) {
875         if (winPriv->PortRec == portPriv)       /* we're already listed */
876             break;
877         winPriv = winPriv->next;
878     }
879 
880     if (!winPriv) {
881         winPriv = calloc(1, sizeof(XF86XVWindowRec));
882         if (!winPriv)
883             return BadAlloc;
884         winPriv->PortRec = portPriv;
885         winPriv->next = PrivRoot;
886         dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, winPriv);
887     }
888 
889     portPriv->pDraw = (DrawablePtr) pWin;
890 
891     return Success;
892 }
893 
894 static void
xf86XVRemovePortFromWindow(WindowPtr pWin,XvPortRecPrivatePtr portPriv)895 xf86XVRemovePortFromWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
896 {
897     XF86XVWindowPtr winPriv, prevPriv = NULL;
898 
899     winPriv = GET_XF86XV_WINDOW(pWin);
900 
901     while (winPriv) {
902         if (winPriv->PortRec == portPriv) {
903             if (prevPriv)
904                 prevPriv->next = winPriv->next;
905             else
906                 dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey,
907                               winPriv->next);
908             free(winPriv);
909             break;
910         }
911         prevPriv = winPriv;
912         winPriv = winPriv->next;
913     }
914     portPriv->pDraw = NULL;
915     if (portPriv->ckeyFilled) {
916         RegionDestroy(portPriv->ckeyFilled);
917         portPriv->ckeyFilled = NULL;
918     }
919     portPriv->clipChanged = FALSE;
920 }
921 
922 static void
xf86XVReputOrStopPort(XvPortRecPrivatePtr pPriv,WindowPtr pWin,Bool visible)923 xf86XVReputOrStopPort(XvPortRecPrivatePtr pPriv, WindowPtr pWin, Bool visible)
924 {
925     if (!visible) {
926         if (pPriv->isOn == XV_ON) {
927             (*pPriv->AdaptorRec->StopVideo) (pPriv->pScrn, pPriv->DevPriv.ptr,
928                                              FALSE);
929             pPriv->isOn = XV_PENDING;
930         }
931 
932         if (!pPriv->type)       /* overlaid still/image */
933             xf86XVRemovePortFromWindow(pWin, pPriv);
934 
935         return;
936     }
937 
938     switch (pPriv->type) {
939     case XvInputMask:
940         xf86XVReputVideo(pPriv);
941         break;
942     case XvOutputMask:
943         xf86XVRegetVideo(pPriv);
944         break;
945     default:                   /* overlaid still/image */
946         if (pPriv->AdaptorRec->ReputImage)
947             xf86XVReputImage(pPriv);
948         break;
949     }
950 }
951 
952 static void
xf86XVReputOrStopAllPorts(ScrnInfoPtr pScrn,Bool onlyChanged)953 xf86XVReputOrStopAllPorts(ScrnInfoPtr pScrn, Bool onlyChanged)
954 {
955     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
956     XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
957     XvAdaptorPtr pa;
958     int c, i;
959 
960     for (c = pxvs->nAdaptors, pa = pxvs->pAdaptors; c > 0; c--, pa++) {
961         XvPortPtr pPort = pa->pPorts;
962 
963         for (i = pa->nPorts; i > 0; i--, pPort++) {
964             XvPortRecPrivatePtr pPriv =
965                 (XvPortRecPrivatePtr) pPort->devPriv.ptr;
966             WindowPtr pWin = (WindowPtr) pPriv->pDraw;
967             Bool visible;
968 
969             if (pPriv->isOn == XV_OFF || !pWin)
970                 continue;
971 
972             if (onlyChanged && !pPriv->clipChanged)
973                 continue;
974 
975             visible = pWin->visibility == VisibilityUnobscured ||
976                 pWin->visibility == VisibilityPartiallyObscured;
977 
978             /*
979              * Stop and remove still/images if
980              * ReputImage isn't supported.
981              */
982             if (!pPriv->type && !pPriv->AdaptorRec->ReputImage)
983                 visible = FALSE;
984 
985             xf86XVReputOrStopPort(pPriv, pWin, visible);
986 
987             pPriv->clipChanged = FALSE;
988         }
989     }
990 }
991 
992 /****  ScreenRec fields ****/
993 
994 static Bool
xf86XVDestroyWindow(WindowPtr pWin)995 xf86XVDestroyWindow(WindowPtr pWin)
996 {
997     ScreenPtr pScreen = pWin->drawable.pScreen;
998     XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
999     XF86XVWindowPtr tmp, WinPriv = GET_XF86XV_WINDOW(pWin);
1000     int ret;
1001 
1002     while (WinPriv) {
1003         XvPortRecPrivatePtr pPriv = WinPriv->PortRec;
1004 
1005         if (pPriv->isOn > XV_OFF) {
1006             (*pPriv->AdaptorRec->StopVideo) (pPriv->pScrn, pPriv->DevPriv.ptr,
1007                                              TRUE);
1008             pPriv->isOn = XV_OFF;
1009         }
1010 
1011         pPriv->pDraw = NULL;
1012         tmp = WinPriv;
1013         WinPriv = WinPriv->next;
1014         free(tmp);
1015     }
1016 
1017     dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, NULL);
1018 
1019     pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
1020     ret = (*pScreen->DestroyWindow) (pWin);
1021     pScreen->DestroyWindow = xf86XVDestroyWindow;
1022 
1023     return ret;
1024 }
1025 
1026 static void
xf86XVPostValidateTree(WindowPtr pWin,WindowPtr pLayerWin,VTKind kind)1027 xf86XVPostValidateTree(WindowPtr pWin, WindowPtr pLayerWin, VTKind kind)
1028 {
1029     ScreenPtr pScreen;
1030     XF86XVScreenPtr ScreenPriv;
1031     ScrnInfoPtr pScrn;
1032 
1033     if (pWin)
1034         pScreen = pWin->drawable.pScreen;
1035     else
1036         pScreen = pLayerWin->drawable.pScreen;
1037 
1038     ScreenPriv = GET_XF86XV_SCREEN(pScreen);
1039     pScrn = xf86ScreenToScrn(pScreen);
1040 
1041     xf86XVReputOrStopAllPorts(pScrn, TRUE);
1042 
1043     pScreen->PostValidateTree = ScreenPriv->PostValidateTree;
1044     if (pScreen->PostValidateTree) {
1045         (*pScreen->PostValidateTree) (pWin, pLayerWin, kind);
1046     }
1047     ScreenPriv->PostValidateTree = PostValidateTreeUndefined;
1048 }
1049 
1050 static void
xf86XVWindowExposures(WindowPtr pWin,RegionPtr reg1)1051 xf86XVWindowExposures(WindowPtr pWin, RegionPtr reg1)
1052 {
1053     ScreenPtr pScreen = pWin->drawable.pScreen;
1054     XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
1055     XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
1056     XvPortRecPrivatePtr pPriv;
1057     Bool AreasExposed;
1058 
1059     AreasExposed = (WinPriv && reg1 && RegionNotEmpty(reg1));
1060 
1061     pScreen->WindowExposures = ScreenPriv->WindowExposures;
1062     (*pScreen->WindowExposures) (pWin, reg1);
1063     pScreen->WindowExposures = xf86XVWindowExposures;
1064 
1065     /* filter out XClearWindow/Area */
1066     if (!pWin->valdata)
1067         return;
1068 
1069     while (WinPriv) {
1070         Bool visible = TRUE;
1071 
1072         pPriv = WinPriv->PortRec;
1073 
1074         /*
1075          * Stop and remove still/images if areas were exposed and
1076          * ReputImage isn't supported.
1077          */
1078         if (!pPriv->type && !pPriv->AdaptorRec->ReputImage)
1079             visible = !AreasExposed;
1080 
1081         /*
1082          * Subtract exposed areas from overlaid image to match textured video
1083          * behavior.
1084          */
1085         if (!pPriv->type && pPriv->clientClip)
1086             RegionSubtract(pPriv->clientClip, pPriv->clientClip, reg1);
1087 
1088         if (visible && pPriv->ckeyFilled) {
1089             RegionRec tmp;
1090 
1091             RegionNull(&tmp);
1092             RegionCopy(&tmp, reg1);
1093             RegionTranslate(&tmp, pWin->drawable.x, pWin->drawable.y);
1094             RegionSubtract(pPriv->ckeyFilled, pPriv->ckeyFilled, &tmp);
1095         }
1096 
1097         WinPriv = WinPriv->next;
1098         xf86XVReputOrStopPort(pPriv, pWin, visible);
1099 
1100         pPriv->clipChanged = FALSE;
1101     }
1102 }
1103 
1104 static void
xf86XVClipNotify(WindowPtr pWin,int dx,int dy)1105 xf86XVClipNotify(WindowPtr pWin, int dx, int dy)
1106 {
1107     ScreenPtr pScreen = pWin->drawable.pScreen;
1108     XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
1109     XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
1110     XvPortRecPrivatePtr pPriv;
1111 
1112     while (WinPriv) {
1113         pPriv = WinPriv->PortRec;
1114 
1115         if (pPriv->pCompositeClip && pPriv->FreeCompositeClip)
1116             RegionDestroy(pPriv->pCompositeClip);
1117 
1118         pPriv->pCompositeClip = NULL;
1119 
1120         pPriv->clipChanged = TRUE;
1121 
1122         if (ScreenPriv->PostValidateTree == PostValidateTreeUndefined) {
1123             ScreenPriv->PostValidateTree = pScreen->PostValidateTree;
1124             pScreen->PostValidateTree = xf86XVPostValidateTree;
1125         }
1126 
1127         WinPriv = WinPriv->next;
1128     }
1129 
1130     if (ScreenPriv->ClipNotify) {
1131         pScreen->ClipNotify = ScreenPriv->ClipNotify;
1132         (*pScreen->ClipNotify) (pWin, dx, dy);
1133         pScreen->ClipNotify = xf86XVClipNotify;
1134     }
1135 }
1136 
1137 /**** Required XvScreenRec fields ****/
1138 
1139 static Bool
xf86XVCloseScreen(ScreenPtr pScreen)1140 xf86XVCloseScreen(ScreenPtr pScreen)
1141 {
1142     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1143     XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
1144     XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
1145     XvAdaptorPtr pa;
1146     int c;
1147 
1148     if (!ScreenPriv)
1149         return TRUE;
1150 
1151     pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
1152     pScreen->WindowExposures = ScreenPriv->WindowExposures;
1153     pScreen->ClipNotify = ScreenPriv->ClipNotify;
1154     pScreen->CloseScreen = ScreenPriv->CloseScreen;
1155 
1156     pScrn->EnterVT = ScreenPriv->EnterVT;
1157     pScrn->LeaveVT = ScreenPriv->LeaveVT;
1158     pScrn->AdjustFrame = ScreenPriv->AdjustFrame;
1159     pScrn->ModeSet = ScreenPriv->ModeSet;
1160 
1161     for (c = 0, pa = pxvs->pAdaptors; c < pxvs->nAdaptors; c++, pa++) {
1162         xf86XVFreeAdaptor(pa);
1163     }
1164 
1165     free(pxvs->pAdaptors);
1166     free(ScreenPriv);
1167 
1168     return pScreen->CloseScreen(pScreen);
1169 }
1170 
1171 /**** ScrnInfoRec fields ****/
1172 
1173 static Bool
xf86XVEnterVT(ScrnInfoPtr pScrn)1174 xf86XVEnterVT(ScrnInfoPtr pScrn)
1175 {
1176     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
1177     XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
1178     Bool ret;
1179 
1180     pScrn->EnterVT = ScreenPriv->EnterVT;
1181     ret = (*ScreenPriv->EnterVT) (pScrn);
1182     ScreenPriv->EnterVT = pScrn->EnterVT;
1183     pScrn->EnterVT = xf86XVEnterVT;
1184 
1185     if (ret)
1186         WalkTree(pScreen, xf86XVReputAllVideo, 0);
1187 
1188     return ret;
1189 }
1190 
1191 static void
xf86XVLeaveVT(ScrnInfoPtr pScrn)1192 xf86XVLeaveVT(ScrnInfoPtr pScrn)
1193 {
1194     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
1195     XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
1196     XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
1197     XvAdaptorPtr pAdaptor;
1198     XvPortPtr pPort;
1199     XvPortRecPrivatePtr pPriv;
1200     int i, j;
1201 
1202     for (i = 0; i < pxvs->nAdaptors; i++) {
1203         pAdaptor = &pxvs->pAdaptors[i];
1204         for (j = 0; j < pAdaptor->nPorts; j++) {
1205             pPort = &pAdaptor->pPorts[j];
1206             pPriv = (XvPortRecPrivatePtr) pPort->devPriv.ptr;
1207             if (pPriv->isOn > XV_OFF) {
1208 
1209                 (*pPriv->AdaptorRec->StopVideo) (pPriv->pScrn,
1210                                                  pPriv->DevPriv.ptr, TRUE);
1211                 pPriv->isOn = XV_OFF;
1212 
1213                 if (pPriv->pCompositeClip && pPriv->FreeCompositeClip)
1214                     RegionDestroy(pPriv->pCompositeClip);
1215 
1216                 pPriv->pCompositeClip = NULL;
1217 
1218                 if (!pPriv->type && pPriv->pDraw) {     /* still */
1219                     xf86XVRemovePortFromWindow((WindowPtr) pPriv->pDraw, pPriv);
1220                 }
1221             }
1222         }
1223     }
1224 
1225     pScrn->LeaveVT = ScreenPriv->LeaveVT;
1226     (*ScreenPriv->LeaveVT) (pScrn);
1227     ScreenPriv->LeaveVT = pScrn->LeaveVT;
1228     pScrn->LeaveVT = xf86XVLeaveVT;
1229 }
1230 
1231 static void
xf86XVAdjustFrame(ScrnInfoPtr pScrn,int x,int y)1232 xf86XVAdjustFrame(ScrnInfoPtr pScrn, int x, int y)
1233 {
1234     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
1235     XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
1236 
1237     if (ScreenPriv->AdjustFrame) {
1238         pScrn->AdjustFrame = ScreenPriv->AdjustFrame;
1239         (*pScrn->AdjustFrame) (pScrn, x, y);
1240         pScrn->AdjustFrame = xf86XVAdjustFrame;
1241     }
1242 
1243     xf86XVReputOrStopAllPorts(pScrn, FALSE);
1244 }
1245 
1246 static void
xf86XVModeSet(ScrnInfoPtr pScrn)1247 xf86XVModeSet(ScrnInfoPtr pScrn)
1248 {
1249     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
1250     XF86XVScreenPtr ScreenPriv;
1251 
1252     /* Can be called before pScrn->pScreen is set */
1253     if (!pScreen)
1254         return;
1255 
1256     ScreenPriv = GET_XF86XV_SCREEN(pScreen);
1257 
1258     if (ScreenPriv->ModeSet) {
1259         pScrn->ModeSet = ScreenPriv->ModeSet;
1260         (*pScrn->ModeSet) (pScrn);
1261         pScrn->ModeSet = xf86XVModeSet;
1262     }
1263 
1264     xf86XVReputOrStopAllPorts(pScrn, FALSE);
1265 }
1266 
1267 /**** XvAdaptorRec fields ****/
1268 
1269 static int
xf86XVPutVideo(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)1270 xf86XVPutVideo(DrawablePtr pDraw,
1271                XvPortPtr pPort,
1272                GCPtr pGC,
1273                INT16 vid_x, INT16 vid_y,
1274                CARD16 vid_w, CARD16 vid_h,
1275                INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
1276 {
1277     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1278     int result;
1279 
1280     /* No dumping video to pixmaps... For now anyhow */
1281     if (pDraw->type != DRAWABLE_WINDOW) {
1282         pPort->pDraw = (DrawablePtr) NULL;
1283         return BadAlloc;
1284     }
1285 
1286     /* If we are changing windows, unregister our port in the old window */
1287     if (portPriv->pDraw && (portPriv->pDraw != pDraw))
1288         xf86XVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
1289 
1290     /* Register our port with the new window */
1291     result = xf86XVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
1292     if (result != Success)
1293         return result;
1294 
1295     portPriv->type = XvInputMask;
1296 
1297     /* save a copy of these parameters */
1298     portPriv->vid_x = vid_x;
1299     portPriv->vid_y = vid_y;
1300     portPriv->vid_w = vid_w;
1301     portPriv->vid_h = vid_h;
1302     portPriv->drw_x = drw_x;
1303     portPriv->drw_y = drw_y;
1304     portPriv->drw_w = drw_w;
1305     portPriv->drw_h = drw_h;
1306 
1307     /* make sure we have the most recent copy of the clientClip */
1308     xf86XVCopyClip(portPriv, pGC);
1309 
1310     /* To indicate to the DI layer that we were successful */
1311     pPort->pDraw = pDraw;
1312 
1313     if (!portPriv->pScrn->vtSema)
1314         return Success;         /* Success ? */
1315 
1316     return (xf86XVReputVideo(portPriv));
1317 }
1318 
1319 static int
xf86XVPutStill(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)1320 xf86XVPutStill(DrawablePtr pDraw,
1321                XvPortPtr pPort,
1322                GCPtr pGC,
1323                INT16 vid_x, INT16 vid_y,
1324                CARD16 vid_w, CARD16 vid_h,
1325                INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
1326 {
1327     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1328     RegionRec WinRegion;
1329     RegionRec ClipRegion;
1330     BoxRec WinBox;
1331     int ret = Success;
1332     Bool clippedAway = FALSE;
1333 
1334     if (pDraw->type != DRAWABLE_WINDOW)
1335         return BadAlloc;
1336 
1337     if (!portPriv->pScrn->vtSema)
1338         return Success;         /* Success ? */
1339 
1340     WinBox.x1 = pDraw->x + drw_x;
1341     WinBox.y1 = pDraw->y + drw_y;
1342     WinBox.x2 = WinBox.x1 + drw_w;
1343     WinBox.y2 = WinBox.y1 + drw_h;
1344 
1345     xf86XVCopyCompositeClip(portPriv, pGC, pDraw);
1346 
1347     RegionInit(&WinRegion, &WinBox, 1);
1348     RegionNull(&ClipRegion);
1349     RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
1350 
1351     if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
1352         RegionRec VPReg;
1353         BoxRec VPBox;
1354 
1355         VPBox.x1 = portPriv->pScrn->frameX0;
1356         VPBox.y1 = portPriv->pScrn->frameY0;
1357         VPBox.x2 = portPriv->pScrn->frameX1 + 1;
1358         VPBox.y2 = portPriv->pScrn->frameY1 + 1;
1359 
1360         RegionInit(&VPReg, &VPBox, 1);
1361         RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
1362         RegionUninit(&VPReg);
1363     }
1364 
1365     if (portPriv->pDraw) {
1366         xf86XVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
1367     }
1368 
1369     if (!RegionNotEmpty(&ClipRegion)) {
1370         clippedAway = TRUE;
1371         goto PUT_STILL_BAILOUT;
1372     }
1373 
1374     ret = (*portPriv->AdaptorRec->PutStill) (portPriv->pScrn,
1375                                              vid_x, vid_y, WinBox.x1, WinBox.y1,
1376                                              vid_w, vid_h, drw_w, drw_h,
1377                                              &ClipRegion, portPriv->DevPriv.ptr,
1378                                              pDraw);
1379 
1380     if ((ret == Success) &&
1381         (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_STILLS)) {
1382 
1383         xf86XVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
1384         portPriv->isOn = XV_ON;
1385         portPriv->vid_x = vid_x;
1386         portPriv->vid_y = vid_y;
1387         portPriv->vid_w = vid_w;
1388         portPriv->vid_h = vid_h;
1389         portPriv->drw_x = drw_x;
1390         portPriv->drw_y = drw_y;
1391         portPriv->drw_w = drw_w;
1392         portPriv->drw_h = drw_h;
1393         portPriv->type = 0;     /* no mask means it's transient and should
1394                                    not be reput once it's removed */
1395         pPort->pDraw = pDraw;   /* make sure we can get stop requests */
1396     }
1397 
1398  PUT_STILL_BAILOUT:
1399 
1400     if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
1401         (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
1402                                             portPriv->DevPriv.ptr, FALSE);
1403         portPriv->isOn = XV_PENDING;
1404     }
1405 
1406     /* This clip was copied and only good for one shot */
1407     if (!portPriv->FreeCompositeClip)
1408         portPriv->pCompositeClip = NULL;
1409 
1410     RegionUninit(&WinRegion);
1411     RegionUninit(&ClipRegion);
1412 
1413     return ret;
1414 }
1415 
1416 static int
xf86XVGetVideo(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)1417 xf86XVGetVideo(DrawablePtr pDraw,
1418                XvPortPtr pPort,
1419                GCPtr pGC,
1420                INT16 vid_x, INT16 vid_y,
1421                CARD16 vid_w, CARD16 vid_h,
1422                INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
1423 {
1424     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1425     int result;
1426 
1427     /* No pixmaps... For now anyhow */
1428     if (pDraw->type != DRAWABLE_WINDOW) {
1429         pPort->pDraw = (DrawablePtr) NULL;
1430         return BadAlloc;
1431     }
1432 
1433     /* If we are changing windows, unregister our port in the old window */
1434     if (portPriv->pDraw && (portPriv->pDraw != pDraw))
1435         xf86XVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
1436 
1437     /* Register our port with the new window */
1438     result = xf86XVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
1439     if (result != Success)
1440         return result;
1441 
1442     portPriv->type = XvOutputMask;
1443 
1444     /* save a copy of these parameters */
1445     portPriv->vid_x = vid_x;
1446     portPriv->vid_y = vid_y;
1447     portPriv->vid_w = vid_w;
1448     portPriv->vid_h = vid_h;
1449     portPriv->drw_x = drw_x;
1450     portPriv->drw_y = drw_y;
1451     portPriv->drw_w = drw_w;
1452     portPriv->drw_h = drw_h;
1453 
1454     /* make sure we have the most recent copy of the clientClip */
1455     xf86XVCopyClip(portPriv, pGC);
1456 
1457     /* To indicate to the DI layer that we were successful */
1458     pPort->pDraw = pDraw;
1459 
1460     if (!portPriv->pScrn->vtSema)
1461         return Success;         /* Success ? */
1462 
1463     return (xf86XVRegetVideo(portPriv));
1464 }
1465 
1466 static int
xf86XVGetStill(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)1467 xf86XVGetStill(DrawablePtr pDraw,
1468                XvPortPtr pPort,
1469                GCPtr pGC,
1470                INT16 vid_x, INT16 vid_y,
1471                CARD16 vid_w, CARD16 vid_h,
1472                INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
1473 {
1474     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1475     RegionRec WinRegion;
1476     RegionRec ClipRegion;
1477     BoxRec WinBox;
1478     int ret = Success;
1479     Bool clippedAway = FALSE;
1480 
1481     if (pDraw->type != DRAWABLE_WINDOW)
1482         return BadAlloc;
1483 
1484     if (!portPriv->pScrn->vtSema)
1485         return Success;         /* Success ? */
1486 
1487     WinBox.x1 = pDraw->x + drw_x;
1488     WinBox.y1 = pDraw->y + drw_y;
1489     WinBox.x2 = WinBox.x1 + drw_w;
1490     WinBox.y2 = WinBox.y1 + drw_h;
1491 
1492     RegionInit(&WinRegion, &WinBox, 1);
1493     RegionNull(&ClipRegion);
1494     RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
1495 
1496     if (portPriv->pDraw) {
1497         xf86XVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
1498     }
1499 
1500     if (!RegionNotEmpty(&ClipRegion)) {
1501         clippedAway = TRUE;
1502         goto GET_STILL_BAILOUT;
1503     }
1504 
1505     ret = (*portPriv->AdaptorRec->GetStill) (portPriv->pScrn,
1506                                              vid_x, vid_y, WinBox.x1, WinBox.y1,
1507                                              vid_w, vid_h, drw_w, drw_h,
1508                                              &ClipRegion, portPriv->DevPriv.ptr,
1509                                              pDraw);
1510 
1511  GET_STILL_BAILOUT:
1512 
1513     if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
1514         (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
1515                                             portPriv->DevPriv.ptr, FALSE);
1516         portPriv->isOn = XV_PENDING;
1517     }
1518 
1519     RegionUninit(&WinRegion);
1520     RegionUninit(&ClipRegion);
1521 
1522     return ret;
1523 }
1524 
1525 static int
xf86XVStopVideo(XvPortPtr pPort,DrawablePtr pDraw)1526 xf86XVStopVideo(XvPortPtr pPort, DrawablePtr pDraw)
1527 {
1528     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1529 
1530     if (pDraw->type != DRAWABLE_WINDOW)
1531         return BadAlloc;
1532 
1533     xf86XVRemovePortFromWindow((WindowPtr) pDraw, portPriv);
1534 
1535     if (!portPriv->pScrn->vtSema)
1536         return Success;         /* Success ? */
1537 
1538     /* Must free resources. */
1539 
1540     if (portPriv->isOn > XV_OFF) {
1541         (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
1542                                             portPriv->DevPriv.ptr, TRUE);
1543         portPriv->isOn = XV_OFF;
1544     }
1545 
1546     return Success;
1547 }
1548 
1549 static int
xf86XVSetPortAttribute(XvPortPtr pPort,Atom attribute,INT32 value)1550 xf86XVSetPortAttribute(XvPortPtr pPort, Atom attribute, INT32 value)
1551 {
1552     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1553 
1554     return ((*portPriv->AdaptorRec->SetPortAttribute) (portPriv->pScrn,
1555                                                        attribute, value,
1556                                                        portPriv->DevPriv.ptr));
1557 }
1558 
1559 static int
xf86XVGetPortAttribute(XvPortPtr pPort,Atom attribute,INT32 * p_value)1560 xf86XVGetPortAttribute(XvPortPtr pPort, Atom attribute, INT32 *p_value)
1561 {
1562     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1563 
1564     return ((*portPriv->AdaptorRec->GetPortAttribute) (portPriv->pScrn,
1565                                                        attribute, p_value,
1566                                                        portPriv->DevPriv.ptr));
1567 }
1568 
1569 static int
xf86XVQueryBestSize(XvPortPtr pPort,CARD8 motion,CARD16 vid_w,CARD16 vid_h,CARD16 drw_w,CARD16 drw_h,unsigned int * p_w,unsigned int * p_h)1570 xf86XVQueryBestSize(XvPortPtr pPort,
1571                     CARD8 motion,
1572                     CARD16 vid_w, CARD16 vid_h,
1573                     CARD16 drw_w, CARD16 drw_h,
1574                     unsigned int *p_w, unsigned int *p_h)
1575 {
1576     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1577 
1578     (*portPriv->AdaptorRec->QueryBestSize) (portPriv->pScrn,
1579                                             (Bool) motion, vid_w, vid_h, drw_w,
1580                                             drw_h, p_w, p_h,
1581                                             portPriv->DevPriv.ptr);
1582 
1583     return Success;
1584 }
1585 
1586 static int
xf86XVPutImage(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)1587 xf86XVPutImage(DrawablePtr pDraw,
1588                XvPortPtr pPort,
1589                GCPtr pGC,
1590                INT16 src_x, INT16 src_y,
1591                CARD16 src_w, CARD16 src_h,
1592                INT16 drw_x, INT16 drw_y,
1593                CARD16 drw_w, CARD16 drw_h,
1594                XvImagePtr format,
1595                unsigned char *data, Bool sync, CARD16 width, CARD16 height)
1596 {
1597     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1598     RegionRec WinRegion;
1599     RegionRec ClipRegion;
1600     BoxRec WinBox;
1601     int ret = Success;
1602     Bool clippedAway = FALSE;
1603 
1604     if (pDraw->type != DRAWABLE_WINDOW)
1605         return BadAlloc;
1606 
1607     if (!portPriv->pScrn->vtSema)
1608         return Success;         /* Success ? */
1609 
1610     xf86XVCopyCompositeClip(portPriv, pGC, pDraw);
1611 
1612     WinBox.x1 = pDraw->x + drw_x;
1613     WinBox.y1 = pDraw->y + drw_y;
1614     WinBox.x2 = WinBox.x1 + drw_w;
1615     WinBox.y2 = WinBox.y1 + drw_h;
1616 
1617     RegionInit(&WinRegion, &WinBox, 1);
1618     RegionNull(&ClipRegion);
1619     RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
1620 
1621     if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
1622         RegionRec VPReg;
1623         BoxRec VPBox;
1624 
1625         VPBox.x1 = portPriv->pScrn->frameX0;
1626         VPBox.y1 = portPriv->pScrn->frameY0;
1627         VPBox.x2 = portPriv->pScrn->frameX1 + 1;
1628         VPBox.y2 = portPriv->pScrn->frameY1 + 1;
1629 
1630         RegionInit(&VPReg, &VPBox, 1);
1631         RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
1632         RegionUninit(&VPReg);
1633     }
1634 
1635     /* If we are changing windows, unregister our port in the old window */
1636     if (portPriv->pDraw && (portPriv->pDraw != pDraw))
1637         xf86XVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
1638 
1639     /* Register our port with the new window */
1640     ret = xf86XVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
1641     if (ret != Success)
1642         goto PUT_IMAGE_BAILOUT;
1643 
1644     if (!RegionNotEmpty(&ClipRegion)) {
1645         clippedAway = TRUE;
1646         goto PUT_IMAGE_BAILOUT;
1647     }
1648 
1649     ret = (*portPriv->AdaptorRec->PutImage) (portPriv->pScrn,
1650                                              src_x, src_y, WinBox.x1, WinBox.y1,
1651                                              src_w, src_h, drw_w, drw_h,
1652                                              format->id, data, width, height,
1653                                              sync, &ClipRegion,
1654                                              portPriv->DevPriv.ptr, pDraw);
1655 
1656     if ((ret == Success) &&
1657         (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_IMAGES)) {
1658 
1659         portPriv->isOn = XV_ON;
1660         portPriv->vid_x = src_x;
1661         portPriv->vid_y = src_y;
1662         portPriv->vid_w = src_w;
1663         portPriv->vid_h = src_h;
1664         portPriv->drw_x = drw_x;
1665         portPriv->drw_y = drw_y;
1666         portPriv->drw_w = drw_w;
1667         portPriv->drw_h = drw_h;
1668         portPriv->type = 0;     /* no mask means it's transient and should
1669                                    not be reput once it's removed */
1670         pPort->pDraw = pDraw;   /* make sure we can get stop requests */
1671     }
1672 
1673  PUT_IMAGE_BAILOUT:
1674 
1675     if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
1676         (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
1677                                             portPriv->DevPriv.ptr, FALSE);
1678         portPriv->isOn = XV_PENDING;
1679     }
1680 
1681     /* This clip was copied and only good for one shot */
1682     if (!portPriv->FreeCompositeClip)
1683         portPriv->pCompositeClip = NULL;
1684 
1685     RegionUninit(&WinRegion);
1686     RegionUninit(&ClipRegion);
1687 
1688     return ret;
1689 }
1690 
1691 static int
xf86XVQueryImageAttributes(XvPortPtr pPort,XvImagePtr format,CARD16 * width,CARD16 * height,int * pitches,int * offsets)1692 xf86XVQueryImageAttributes(XvPortPtr pPort,
1693                            XvImagePtr format,
1694                            CARD16 *width,
1695                            CARD16 *height, int *pitches, int *offsets)
1696 {
1697     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
1698 
1699     return (*portPriv->AdaptorRec->QueryImageAttributes) (portPriv->pScrn,
1700                                                           format->id, width,
1701                                                           height, pitches,
1702                                                           offsets);
1703 }
1704 
1705 void
xf86XVFillKeyHelperDrawable(DrawablePtr pDraw,CARD32 key,RegionPtr fillboxes)1706 xf86XVFillKeyHelperDrawable(DrawablePtr pDraw, CARD32 key, RegionPtr fillboxes)
1707 {
1708     ScreenPtr pScreen = pDraw->pScreen;
1709 
1710     if (!xf86ScreenToScrn(pScreen)->vtSema)
1711         return;
1712 
1713     XvFillColorKey(pDraw, key, fillboxes);
1714 }
1715 
1716 void
xf86XVFillKeyHelper(ScreenPtr pScreen,CARD32 key,RegionPtr fillboxes)1717 xf86XVFillKeyHelper(ScreenPtr pScreen, CARD32 key, RegionPtr fillboxes)
1718 {
1719     xf86XVFillKeyHelperDrawable(&pScreen->root->drawable, key, fillboxes);
1720 }
1721 
1722 void
xf86XVFillKeyHelperPort(DrawablePtr pDraw,void * data,CARD32 key,RegionPtr clipboxes,Bool fillEverything)1723 xf86XVFillKeyHelperPort(DrawablePtr pDraw, void *data, CARD32 key,
1724                         RegionPtr clipboxes, Bool fillEverything)
1725 {
1726     WindowPtr pWin = (WindowPtr) pDraw;
1727     XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
1728     XvPortRecPrivatePtr portPriv = NULL;
1729     RegionRec reg;
1730     RegionPtr fillboxes;
1731 
1732     while (WinPriv) {
1733         XvPortRecPrivatePtr pPriv = WinPriv->PortRec;
1734 
1735         if (data == pPriv->DevPriv.ptr) {
1736             portPriv = pPriv;
1737             break;
1738         }
1739 
1740         WinPriv = WinPriv->next;
1741     }
1742 
1743     if (!portPriv)
1744         return;
1745 
1746     if (!portPriv->ckeyFilled)
1747         portPriv->ckeyFilled = RegionCreate(NULL, 0);
1748 
1749     if (!fillEverything) {
1750         RegionNull(&reg);
1751         fillboxes = &reg;
1752         RegionSubtract(fillboxes, clipboxes, portPriv->ckeyFilled);
1753 
1754         if (!RegionNotEmpty(fillboxes))
1755             goto out;
1756     }
1757     else
1758         fillboxes = clipboxes;
1759 
1760     RegionCopy(portPriv->ckeyFilled, clipboxes);
1761 
1762     xf86XVFillKeyHelperDrawable(pDraw, key, fillboxes);
1763  out:
1764     if (!fillEverything)
1765         RegionUninit(&reg);
1766 }
1767 
1768 /* xf86XVClipVideoHelper -
1769 
1770    Takes the dst box in standard X BoxRec form (top and left
1771    edges inclusive, bottom and right exclusive).  The new dst
1772    box is returned.  The source boundaries are given (x1, y1
1773    inclusive, x2, y2 exclusive) and returned are the new source
1774    boundaries in 16.16 fixed point.
1775 */
1776 
1777 Bool
xf86XVClipVideoHelper(BoxPtr dst,INT32 * xa,INT32 * xb,INT32 * ya,INT32 * yb,RegionPtr reg,INT32 width,INT32 height)1778 xf86XVClipVideoHelper(BoxPtr dst,
1779                       INT32 *xa,
1780                       INT32 *xb,
1781                       INT32 *ya,
1782                       INT32 *yb, RegionPtr reg, INT32 width, INT32 height)
1783 {
1784     double xsw, xdw, ysw, ydw;
1785     INT32 delta;
1786     BoxPtr extents = RegionExtents(reg);
1787     int diff;
1788 
1789     xsw = (*xb - *xa) << 16;
1790     xdw = dst->x2 - dst->x1;
1791     ysw = (*yb - *ya) << 16;
1792     ydw = dst->y2 - dst->y1;
1793 
1794     *xa <<= 16;
1795     *xb <<= 16;
1796     *ya <<= 16;
1797     *yb <<= 16;
1798 
1799     diff = extents->x1 - dst->x1;
1800     if (diff > 0) {
1801         dst->x1 = extents->x1;
1802         *xa += (diff * xsw) / xdw;
1803     }
1804     diff = dst->x2 - extents->x2;
1805     if (diff > 0) {
1806         dst->x2 = extents->x2;
1807         *xb -= (diff * xsw) / xdw;
1808     }
1809     diff = extents->y1 - dst->y1;
1810     if (diff > 0) {
1811         dst->y1 = extents->y1;
1812         *ya += (diff * ysw) / ydw;
1813     }
1814     diff = dst->y2 - extents->y2;
1815     if (diff > 0) {
1816         dst->y2 = extents->y2;
1817         *yb -= (diff * ysw) / ydw;
1818     }
1819 
1820     if (*xa < 0) {
1821         diff = (((-*xa) * xdw) + xsw - 1) / xsw;
1822         dst->x1 += diff;
1823         *xa += (diff * xsw) / xdw;
1824     }
1825     delta = *xb - (width << 16);
1826     if (delta > 0) {
1827         diff = ((delta * xdw) + xsw - 1) / xsw;
1828         dst->x2 -= diff;
1829         *xb -= (diff * xsw) / xdw;
1830     }
1831     if (*xa >= *xb)
1832         return FALSE;
1833 
1834     if (*ya < 0) {
1835         diff = (((-*ya) * ydw) + ysw - 1) / ysw;
1836         dst->y1 += diff;
1837         *ya += (diff * ysw) / ydw;
1838     }
1839     delta = *yb - (height << 16);
1840     if (delta > 0) {
1841         diff = ((delta * ydw) + ysw - 1) / ysw;
1842         dst->y2 -= diff;
1843         *yb -= (diff * ysw) / ydw;
1844     }
1845     if (*ya >= *yb)
1846         return FALSE;
1847 
1848     if ((dst->x1 > extents->x1) || (dst->x2 < extents->x2) ||
1849         (dst->y1 > extents->y1) || (dst->y2 < extents->y2)) {
1850         RegionRec clipReg;
1851 
1852         RegionInit(&clipReg, dst, 1);
1853         RegionIntersect(reg, reg, &clipReg);
1854         RegionUninit(&clipReg);
1855     }
1856     return TRUE;
1857 }
1858 
1859 void
xf86XVCopyYUV12ToPacked(const void * srcy,const void * srcv,const void * srcu,void * dst,int srcPitchy,int srcPitchuv,int dstPitch,int h,int w)1860 xf86XVCopyYUV12ToPacked(const void *srcy,
1861                         const void *srcv,
1862                         const void *srcu,
1863                         void *dst,
1864                         int srcPitchy,
1865                         int srcPitchuv, int dstPitch, int h, int w)
1866 {
1867     CARD32 *Dst;
1868     const CARD8 *Y, *U, *V;
1869     int i, j;
1870 
1871     w >>= 1;
1872 
1873     for (j = 0; j < h; j++) {
1874         Dst = dst;
1875         Y = srcy;
1876         V = srcv;
1877         U = srcu;
1878         i = w;
1879         while (i >= 4) {
1880 #if X_BYTE_ORDER == X_LITTLE_ENDIAN
1881             Dst[0] = Y[0] | (Y[1] << 16) | (U[0] << 8) | (V[0] << 24);
1882             Dst[1] = Y[2] | (Y[3] << 16) | (U[1] << 8) | (V[1] << 24);
1883             Dst[2] = Y[4] | (Y[5] << 16) | (U[2] << 8) | (V[2] << 24);
1884             Dst[3] = Y[6] | (Y[7] << 16) | (U[3] << 8) | (V[3] << 24);
1885 #else
1886             /* This assumes a little-endian framebuffer */
1887             Dst[0] = (Y[0] << 24) | (Y[1] << 8) | (U[0] << 16) | V[0];
1888             Dst[1] = (Y[2] << 24) | (Y[3] << 8) | (U[1] << 16) | V[1];
1889             Dst[2] = (Y[4] << 24) | (Y[5] << 8) | (U[2] << 16) | V[2];
1890             Dst[3] = (Y[6] << 24) | (Y[7] << 8) | (U[3] << 16) | V[3];
1891 #endif
1892             Dst += 4;
1893             Y += 8;
1894             V += 4;
1895             U += 4;
1896             i -= 4;
1897         }
1898 
1899         while (i--) {
1900 #if X_BYTE_ORDER == X_LITTLE_ENDIAN
1901             Dst[0] = Y[0] | (Y[1] << 16) | (U[0] << 8) | (V[0] << 24);
1902 #else
1903             /* This assumes a little-endian framebuffer */
1904             Dst[0] = (Y[0] << 24) | (Y[1] << 8) | (U[0] << 16) | V[0];
1905 #endif
1906             Dst++;
1907             Y += 2;
1908             V++;
1909             U++;
1910         }
1911 
1912         dst = (CARD8 *) dst + dstPitch;
1913         srcy = (const CARD8 *) srcy + srcPitchy;
1914         if (j & 1) {
1915             srcu = (const CARD8 *) srcu + srcPitchuv;
1916             srcv = (const CARD8 *) srcv + srcPitchuv;
1917         }
1918     }
1919 }
1920 
1921 void
xf86XVCopyPacked(const void * src,void * dst,int srcPitch,int dstPitch,int h,int w)1922 xf86XVCopyPacked(const void *src,
1923                  void *dst, int srcPitch, int dstPitch, int h, int w)
1924 {
1925     const CARD32 *Src;
1926     CARD32 *Dst;
1927     int i;
1928 
1929     w >>= 1;
1930     while (--h >= 0) {
1931         do {
1932             Dst = dst;
1933             Src = src;
1934             i = w;
1935             while (i >= 4) {
1936                 Dst[0] = Src[0];
1937                 Dst[1] = Src[1];
1938                 Dst[2] = Src[2];
1939                 Dst[3] = Src[3];
1940                 Dst += 4;
1941                 Src += 4;
1942                 i -= 4;
1943             }
1944             if (!i)
1945                 break;
1946             Dst[0] = Src[0];
1947             if (i == 1)
1948                 break;
1949             Dst[1] = Src[1];
1950             if (i == 2)
1951                 break;
1952             Dst[2] = Src[2];
1953         } while (0);
1954 
1955         src = (const CARD8 *) src + srcPitch;
1956         dst = (CARD8 *) dst + dstPitch;
1957     }
1958 }
1959