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