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(®);
1751 fillboxes = ®
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(®);
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