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