1 /***********************************************************
2 Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts,
3 and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
4 
5                         All Rights Reserved
6 
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Digital or MIT not be
12 used in advertising or publicity pertaining to distribution of the
13 software without specific, written prior permission.
14 
15 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
16 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
17 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21 SOFTWARE.
22 ******************************************************************/
23 
24 #ifdef HAVE_DIX_CONFIG_H
25 #include <dix-config.h>
26 #endif
27 
28 #include <string.h>
29 
30 #include <X11/X.h>
31 #include <X11/Xproto.h>
32 #include "misc.h"
33 #include "scrnintstr.h"
34 #include "windowstr.h"
35 #include "pixmapstr.h"
36 #include "gcstruct.h"
37 #include "dixstruct.h"
38 #include "resource.h"
39 #include "opaque.h"
40 
41 #include <X11/extensions/Xv.h>
42 #include <X11/extensions/Xvproto.h>
43 #include "xvdix.h"
44 #ifdef MITSHM
45 #include <X11/extensions/shmproto.h>
46 #include "shmint.h"
47 #endif
48 
49 #include "xvdisp.h"
50 
51 #ifdef PANORAMIX
52 #include "panoramiX.h"
53 #include "panoramiXsrv.h"
54 
55 unsigned long XvXRTPort;
56 #endif
57 
58 static int
SWriteQueryExtensionReply(ClientPtr client,xvQueryExtensionReply * rep)59 SWriteQueryExtensionReply(ClientPtr client, xvQueryExtensionReply * rep)
60 {
61     swaps(&rep->sequenceNumber);
62     swapl(&rep->length);
63     swaps(&rep->version);
64     swaps(&rep->revision);
65 
66     WriteToClient(client, sz_xvQueryExtensionReply, rep);
67 
68     return Success;
69 }
70 
71 static int
SWriteQueryAdaptorsReply(ClientPtr client,xvQueryAdaptorsReply * rep)72 SWriteQueryAdaptorsReply(ClientPtr client, xvQueryAdaptorsReply * rep)
73 {
74     swaps(&rep->sequenceNumber);
75     swapl(&rep->length);
76     swaps(&rep->num_adaptors);
77 
78     WriteToClient(client, sz_xvQueryAdaptorsReply, rep);
79 
80     return Success;
81 }
82 
83 static int
SWriteQueryEncodingsReply(ClientPtr client,xvQueryEncodingsReply * rep)84 SWriteQueryEncodingsReply(ClientPtr client, xvQueryEncodingsReply * rep)
85 {
86     swaps(&rep->sequenceNumber);
87     swapl(&rep->length);
88     swaps(&rep->num_encodings);
89 
90     WriteToClient(client, sz_xvQueryEncodingsReply, rep);
91 
92     return Success;
93 }
94 
95 static int
SWriteAdaptorInfo(ClientPtr client,xvAdaptorInfo * pAdaptor)96 SWriteAdaptorInfo(ClientPtr client, xvAdaptorInfo * pAdaptor)
97 {
98     swapl(&pAdaptor->base_id);
99     swaps(&pAdaptor->name_size);
100     swaps(&pAdaptor->num_ports);
101     swaps(&pAdaptor->num_formats);
102 
103     WriteToClient(client, sz_xvAdaptorInfo, pAdaptor);
104 
105     return Success;
106 }
107 
108 static int
SWriteEncodingInfo(ClientPtr client,xvEncodingInfo * pEncoding)109 SWriteEncodingInfo(ClientPtr client, xvEncodingInfo * pEncoding)
110 {
111 
112     swapl(&pEncoding->encoding);
113     swaps(&pEncoding->name_size);
114     swaps(&pEncoding->width);
115     swaps(&pEncoding->height);
116     swapl(&pEncoding->rate.numerator);
117     swapl(&pEncoding->rate.denominator);
118     WriteToClient(client, sz_xvEncodingInfo, pEncoding);
119 
120     return Success;
121 }
122 
123 static int
SWriteFormat(ClientPtr client,xvFormat * pFormat)124 SWriteFormat(ClientPtr client, xvFormat * pFormat)
125 {
126     swapl(&pFormat->visual);
127     WriteToClient(client, sz_xvFormat, pFormat);
128 
129     return Success;
130 }
131 
132 static int
SWriteAttributeInfo(ClientPtr client,xvAttributeInfo * pAtt)133 SWriteAttributeInfo(ClientPtr client, xvAttributeInfo * pAtt)
134 {
135     swapl(&pAtt->flags);
136     swapl(&pAtt->size);
137     swapl(&pAtt->min);
138     swapl(&pAtt->max);
139     WriteToClient(client, sz_xvAttributeInfo, pAtt);
140 
141     return Success;
142 }
143 
144 static int
SWriteImageFormatInfo(ClientPtr client,xvImageFormatInfo * pImage)145 SWriteImageFormatInfo(ClientPtr client, xvImageFormatInfo * pImage)
146 {
147     swapl(&pImage->id);
148     swapl(&pImage->red_mask);
149     swapl(&pImage->green_mask);
150     swapl(&pImage->blue_mask);
151     swapl(&pImage->y_sample_bits);
152     swapl(&pImage->u_sample_bits);
153     swapl(&pImage->v_sample_bits);
154     swapl(&pImage->horz_y_period);
155     swapl(&pImage->horz_u_period);
156     swapl(&pImage->horz_v_period);
157     swapl(&pImage->vert_y_period);
158     swapl(&pImage->vert_u_period);
159     swapl(&pImage->vert_v_period);
160 
161     WriteToClient(client, sz_xvImageFormatInfo, pImage);
162 
163     return Success;
164 }
165 
166 static int
SWriteGrabPortReply(ClientPtr client,xvGrabPortReply * rep)167 SWriteGrabPortReply(ClientPtr client, xvGrabPortReply * rep)
168 {
169     swaps(&rep->sequenceNumber);
170     swapl(&rep->length);
171 
172     WriteToClient(client, sz_xvGrabPortReply, rep);
173 
174     return Success;
175 }
176 
177 static int
SWriteGetPortAttributeReply(ClientPtr client,xvGetPortAttributeReply * rep)178 SWriteGetPortAttributeReply(ClientPtr client, xvGetPortAttributeReply * rep)
179 {
180     swaps(&rep->sequenceNumber);
181     swapl(&rep->length);
182     swapl(&rep->value);
183 
184     WriteToClient(client, sz_xvGetPortAttributeReply, rep);
185 
186     return Success;
187 }
188 
189 static int
SWriteQueryBestSizeReply(ClientPtr client,xvQueryBestSizeReply * rep)190 SWriteQueryBestSizeReply(ClientPtr client, xvQueryBestSizeReply * rep)
191 {
192     swaps(&rep->sequenceNumber);
193     swapl(&rep->length);
194     swaps(&rep->actual_width);
195     swaps(&rep->actual_height);
196 
197     WriteToClient(client, sz_xvQueryBestSizeReply, rep);
198 
199     return Success;
200 }
201 
202 static int
SWriteQueryPortAttributesReply(ClientPtr client,xvQueryPortAttributesReply * rep)203 SWriteQueryPortAttributesReply(ClientPtr client,
204                                xvQueryPortAttributesReply * rep)
205 {
206     swaps(&rep->sequenceNumber);
207     swapl(&rep->length);
208     swapl(&rep->num_attributes);
209     swapl(&rep->text_size);
210 
211     WriteToClient(client, sz_xvQueryPortAttributesReply, rep);
212 
213     return Success;
214 }
215 
216 static int
SWriteQueryImageAttributesReply(ClientPtr client,xvQueryImageAttributesReply * rep)217 SWriteQueryImageAttributesReply(ClientPtr client,
218                                 xvQueryImageAttributesReply * rep)
219 {
220     swaps(&rep->sequenceNumber);
221     swapl(&rep->length);
222     swapl(&rep->num_planes);
223     swapl(&rep->data_size);
224     swaps(&rep->width);
225     swaps(&rep->height);
226 
227     WriteToClient(client, sz_xvQueryImageAttributesReply, rep);
228 
229     return Success;
230 }
231 
232 static int
SWriteListImageFormatsReply(ClientPtr client,xvListImageFormatsReply * rep)233 SWriteListImageFormatsReply(ClientPtr client, xvListImageFormatsReply * rep)
234 {
235     swaps(&rep->sequenceNumber);
236     swapl(&rep->length);
237     swapl(&rep->num_formats);
238 
239     WriteToClient(client, sz_xvListImageFormatsReply, rep);
240 
241     return Success;
242 }
243 
244 #define _WriteQueryAdaptorsReply(_c,_d) \
245   if ((_c)->swapped) SWriteQueryAdaptorsReply(_c, _d); \
246   else WriteToClient(_c, sz_xvQueryAdaptorsReply, _d)
247 
248 #define _WriteQueryExtensionReply(_c,_d) \
249   if ((_c)->swapped) SWriteQueryExtensionReply(_c, _d); \
250   else WriteToClient(_c, sz_xvQueryExtensionReply, _d)
251 
252 #define _WriteQueryEncodingsReply(_c,_d) \
253   if ((_c)->swapped) SWriteQueryEncodingsReply(_c, _d); \
254   else WriteToClient(_c, sz_xvQueryEncodingsReply, _d)
255 
256 #define _WriteAdaptorInfo(_c,_d) \
257   if ((_c)->swapped) SWriteAdaptorInfo(_c, _d); \
258   else WriteToClient(_c, sz_xvAdaptorInfo, _d)
259 
260 #define _WriteAttributeInfo(_c,_d) \
261   if ((_c)->swapped) SWriteAttributeInfo(_c, _d); \
262   else WriteToClient(_c, sz_xvAttributeInfo, _d)
263 
264 #define _WriteEncodingInfo(_c,_d) \
265   if ((_c)->swapped) SWriteEncodingInfo(_c, _d); \
266   else WriteToClient(_c, sz_xvEncodingInfo, _d)
267 
268 #define _WriteFormat(_c,_d) \
269   if ((_c)->swapped) SWriteFormat(_c, _d); \
270   else WriteToClient(_c, sz_xvFormat, _d)
271 
272 #define _WriteGrabPortReply(_c,_d) \
273   if ((_c)->swapped) SWriteGrabPortReply(_c, _d); \
274   else WriteToClient(_c, sz_xvGrabPortReply, _d)
275 
276 #define _WriteGetPortAttributeReply(_c,_d) \
277   if ((_c)->swapped) SWriteGetPortAttributeReply(_c, _d); \
278   else WriteToClient(_c, sz_xvGetPortAttributeReply, _d)
279 
280 #define _WriteQueryBestSizeReply(_c,_d) \
281   if ((_c)->swapped) SWriteQueryBestSizeReply(_c, _d); \
282   else WriteToClient(_c, sz_xvQueryBestSizeReply, _d)
283 
284 #define _WriteQueryPortAttributesReply(_c,_d) \
285   if ((_c)->swapped) SWriteQueryPortAttributesReply(_c, _d); \
286   else WriteToClient(_c, sz_xvQueryPortAttributesReply, _d)
287 
288 #define _WriteQueryImageAttributesReply(_c,_d) \
289   if ((_c)->swapped) SWriteQueryImageAttributesReply(_c, _d); \
290   else WriteToClient(_c, sz_xvQueryImageAttributesReply, _d)
291 
292 #define _WriteListImageFormatsReply(_c,_d) \
293   if ((_c)->swapped) SWriteListImageFormatsReply(_c, _d); \
294   else WriteToClient(_c, sz_xvListImageFormatsReply, _d)
295 
296 #define _WriteImageFormatInfo(_c,_d) \
297   if ((_c)->swapped) SWriteImageFormatInfo(_c, _d); \
298   else WriteToClient(_c, sz_xvImageFormatInfo, _d)
299 
300 static int
ProcXvQueryExtension(ClientPtr client)301 ProcXvQueryExtension(ClientPtr client)
302 {
303     xvQueryExtensionReply rep = {
304         .type = X_Reply,
305         .sequenceNumber = client->sequence,
306         .length = 0,
307         .version = XvVersion,
308         .revision = XvRevision
309     };
310 
311     /* REQUEST(xvQueryExtensionReq); */
312     REQUEST_SIZE_MATCH(xvQueryExtensionReq);
313 
314     _WriteQueryExtensionReply(client, &rep);
315 
316     return Success;
317 }
318 
319 static int
ProcXvQueryAdaptors(ClientPtr client)320 ProcXvQueryAdaptors(ClientPtr client)
321 {
322     xvFormat format;
323     xvAdaptorInfo ainfo;
324     xvQueryAdaptorsReply rep;
325     int totalSize, na, nf, rc;
326     int nameSize;
327     XvAdaptorPtr pa;
328     XvFormatPtr pf;
329     WindowPtr pWin;
330     ScreenPtr pScreen;
331     XvScreenPtr pxvs;
332 
333     REQUEST(xvQueryAdaptorsReq);
334     REQUEST_SIZE_MATCH(xvQueryAdaptorsReq);
335 
336     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
337     if (rc != Success)
338         return rc;
339 
340     pScreen = pWin->drawable.pScreen;
341     pxvs = (XvScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
342                                           XvGetScreenKey());
343     if (!pxvs) {
344         rep = (xvQueryAdaptorsReply) {
345             .type = X_Reply,
346             .sequenceNumber = client->sequence,
347             .length = 0,
348             .num_adaptors = 0
349         };
350 
351         _WriteQueryAdaptorsReply(client, &rep);
352 
353         return Success;
354     }
355 
356     rep = (xvQueryAdaptorsReply) {
357         .type = X_Reply,
358         .sequenceNumber = client->sequence,
359         .num_adaptors = pxvs->nAdaptors
360     };
361 
362     /* CALCULATE THE TOTAL SIZE OF THE REPLY IN BYTES */
363 
364     totalSize = pxvs->nAdaptors * sz_xvAdaptorInfo;
365 
366     /* FOR EACH ADPATOR ADD UP THE BYTES FOR ENCODINGS AND FORMATS */
367 
368     na = pxvs->nAdaptors;
369     pa = pxvs->pAdaptors;
370     while (na--) {
371         totalSize += pad_to_int32(strlen(pa->name));
372         totalSize += pa->nFormats * sz_xvFormat;
373         pa++;
374     }
375 
376     rep.length = bytes_to_int32(totalSize);
377 
378     _WriteQueryAdaptorsReply(client, &rep);
379 
380     na = pxvs->nAdaptors;
381     pa = pxvs->pAdaptors;
382     while (na--) {
383 
384         ainfo.base_id = pa->base_id;
385         ainfo.num_ports = pa->nPorts;
386         ainfo.type = pa->type;
387         ainfo.name_size = nameSize = strlen(pa->name);
388         ainfo.num_formats = pa->nFormats;
389 
390         _WriteAdaptorInfo(client, &ainfo);
391 
392         WriteToClient(client, nameSize, pa->name);
393 
394         nf = pa->nFormats;
395         pf = pa->pFormats;
396         while (nf--) {
397             format.depth = pf->depth;
398             format.visual = pf->visual;
399             _WriteFormat(client, &format);
400             pf++;
401         }
402 
403         pa++;
404 
405     }
406 
407     return Success;
408 }
409 
410 static int
ProcXvQueryEncodings(ClientPtr client)411 ProcXvQueryEncodings(ClientPtr client)
412 {
413     xvEncodingInfo einfo;
414     xvQueryEncodingsReply rep;
415     int totalSize;
416     int nameSize;
417     XvPortPtr pPort;
418     int ne;
419     XvEncodingPtr pe;
420 
421     REQUEST(xvQueryEncodingsReq);
422     REQUEST_SIZE_MATCH(xvQueryEncodingsReq);
423 
424     VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
425 
426     rep = (xvQueryEncodingsReply) {
427         .type = X_Reply,
428         .sequenceNumber = client->sequence,
429         .num_encodings = pPort->pAdaptor->nEncodings
430     };
431 
432     /* FOR EACH ENCODING ADD UP THE BYTES FOR ENCODING NAMES */
433 
434     ne = pPort->pAdaptor->nEncodings;
435     pe = pPort->pAdaptor->pEncodings;
436     totalSize = ne * sz_xvEncodingInfo;
437     while (ne--) {
438         totalSize += pad_to_int32(strlen(pe->name));
439         pe++;
440     }
441 
442     rep.length = bytes_to_int32(totalSize);
443 
444     _WriteQueryEncodingsReply(client, &rep);
445 
446     ne = pPort->pAdaptor->nEncodings;
447     pe = pPort->pAdaptor->pEncodings;
448     while (ne--) {
449         einfo.encoding = pe->id;
450         einfo.name_size = nameSize = strlen(pe->name);
451         einfo.width = pe->width;
452         einfo.height = pe->height;
453         einfo.rate.numerator = pe->rate.numerator;
454         einfo.rate.denominator = pe->rate.denominator;
455         _WriteEncodingInfo(client, &einfo);
456         WriteToClient(client, nameSize, pe->name);
457         pe++;
458     }
459 
460     return Success;
461 }
462 
463 static int
ProcXvPutVideo(ClientPtr client)464 ProcXvPutVideo(ClientPtr client)
465 {
466     DrawablePtr pDraw;
467     XvPortPtr pPort;
468     GCPtr pGC;
469     int status;
470 
471     REQUEST(xvPutVideoReq);
472     REQUEST_SIZE_MATCH(xvPutVideoReq);
473 
474     VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
475     VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
476 
477     if (!(pPort->pAdaptor->type & XvInputMask) ||
478         !(pPort->pAdaptor->type & XvVideoMask)) {
479         client->errorValue = stuff->port;
480         return BadMatch;
481     }
482 
483     status = XvdiMatchPort(pPort, pDraw);
484     if (status != Success) {
485         return status;
486     }
487 
488     return XvdiPutVideo(client, pDraw, pPort, pGC, stuff->vid_x, stuff->vid_y,
489                         stuff->vid_w, stuff->vid_h, stuff->drw_x, stuff->drw_y,
490                         stuff->drw_w, stuff->drw_h);
491 }
492 
493 static int
ProcXvPutStill(ClientPtr client)494 ProcXvPutStill(ClientPtr client)
495 {
496     DrawablePtr pDraw;
497     XvPortPtr pPort;
498     GCPtr pGC;
499     int status;
500 
501     REQUEST(xvPutStillReq);
502     REQUEST_SIZE_MATCH(xvPutStillReq);
503 
504     VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
505     VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
506 
507     if (!(pPort->pAdaptor->type & XvInputMask) ||
508         !(pPort->pAdaptor->type & XvStillMask)) {
509         client->errorValue = stuff->port;
510         return BadMatch;
511     }
512 
513     status = XvdiMatchPort(pPort, pDraw);
514     if (status != Success) {
515         return status;
516     }
517 
518     return XvdiPutStill(client, pDraw, pPort, pGC, stuff->vid_x, stuff->vid_y,
519                         stuff->vid_w, stuff->vid_h, stuff->drw_x, stuff->drw_y,
520                         stuff->drw_w, stuff->drw_h);
521 }
522 
523 static int
ProcXvGetVideo(ClientPtr client)524 ProcXvGetVideo(ClientPtr client)
525 {
526     DrawablePtr pDraw;
527     XvPortPtr pPort;
528     GCPtr pGC;
529     int status;
530 
531     REQUEST(xvGetVideoReq);
532     REQUEST_SIZE_MATCH(xvGetVideoReq);
533 
534     VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixReadAccess);
535     VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
536 
537     if (!(pPort->pAdaptor->type & XvOutputMask) ||
538         !(pPort->pAdaptor->type & XvVideoMask)) {
539         client->errorValue = stuff->port;
540         return BadMatch;
541     }
542 
543     status = XvdiMatchPort(pPort, pDraw);
544     if (status != Success) {
545         return status;
546     }
547 
548     return XvdiGetVideo(client, pDraw, pPort, pGC, stuff->vid_x, stuff->vid_y,
549                         stuff->vid_w, stuff->vid_h, stuff->drw_x, stuff->drw_y,
550                         stuff->drw_w, stuff->drw_h);
551 }
552 
553 static int
ProcXvGetStill(ClientPtr client)554 ProcXvGetStill(ClientPtr client)
555 {
556     DrawablePtr pDraw;
557     XvPortPtr pPort;
558     GCPtr pGC;
559     int status;
560 
561     REQUEST(xvGetStillReq);
562     REQUEST_SIZE_MATCH(xvGetStillReq);
563 
564     VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixReadAccess);
565     VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
566 
567     if (!(pPort->pAdaptor->type & XvOutputMask) ||
568         !(pPort->pAdaptor->type & XvStillMask)) {
569         client->errorValue = stuff->port;
570         return BadMatch;
571     }
572 
573     status = XvdiMatchPort(pPort, pDraw);
574     if (status != Success) {
575         return status;
576     }
577 
578     return XvdiGetStill(client, pDraw, pPort, pGC, stuff->vid_x, stuff->vid_y,
579                         stuff->vid_w, stuff->vid_h, stuff->drw_x, stuff->drw_y,
580                         stuff->drw_w, stuff->drw_h);
581 }
582 
583 static int
ProcXvSelectVideoNotify(ClientPtr client)584 ProcXvSelectVideoNotify(ClientPtr client)
585 {
586     DrawablePtr pDraw;
587     int rc;
588 
589     REQUEST(xvSelectVideoNotifyReq);
590     REQUEST_SIZE_MATCH(xvSelectVideoNotifyReq);
591 
592     rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
593                            DixReceiveAccess);
594     if (rc != Success)
595         return rc;
596 
597     return XvdiSelectVideoNotify(client, pDraw, stuff->onoff);
598 }
599 
600 static int
ProcXvSelectPortNotify(ClientPtr client)601 ProcXvSelectPortNotify(ClientPtr client)
602 {
603     XvPortPtr pPort;
604 
605     REQUEST(xvSelectPortNotifyReq);
606     REQUEST_SIZE_MATCH(xvSelectPortNotifyReq);
607 
608     VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
609 
610     return XvdiSelectPortNotify(client, pPort, stuff->onoff);
611 }
612 
613 static int
ProcXvGrabPort(ClientPtr client)614 ProcXvGrabPort(ClientPtr client)
615 {
616     int result, status;
617     XvPortPtr pPort;
618     xvGrabPortReply rep;
619 
620     REQUEST(xvGrabPortReq);
621     REQUEST_SIZE_MATCH(xvGrabPortReq);
622 
623     VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
624 
625     status = XvdiGrabPort(client, pPort, stuff->time, &result);
626 
627     if (status != Success) {
628         return status;
629     }
630     rep = (xvGrabPortReply) {
631         .type = X_Reply,
632         .sequenceNumber = client->sequence,
633         .length = 0,
634         .result = result
635     };
636 
637     _WriteGrabPortReply(client, &rep);
638 
639     return Success;
640 }
641 
642 static int
ProcXvUngrabPort(ClientPtr client)643 ProcXvUngrabPort(ClientPtr client)
644 {
645     XvPortPtr pPort;
646 
647     REQUEST(xvGrabPortReq);
648     REQUEST_SIZE_MATCH(xvGrabPortReq);
649 
650     VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
651 
652     return XvdiUngrabPort(client, pPort, stuff->time);
653 }
654 
655 static int
ProcXvStopVideo(ClientPtr client)656 ProcXvStopVideo(ClientPtr client)
657 {
658     int ret;
659     DrawablePtr pDraw;
660     XvPortPtr pPort;
661 
662     REQUEST(xvStopVideoReq);
663     REQUEST_SIZE_MATCH(xvStopVideoReq);
664 
665     VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
666 
667     ret = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixWriteAccess);
668     if (ret != Success)
669         return ret;
670 
671     return XvdiStopVideo(client, pPort, pDraw);
672 }
673 
674 static int
ProcXvSetPortAttribute(ClientPtr client)675 ProcXvSetPortAttribute(ClientPtr client)
676 {
677     int status;
678     XvPortPtr pPort;
679 
680     REQUEST(xvSetPortAttributeReq);
681     REQUEST_SIZE_MATCH(xvSetPortAttributeReq);
682 
683     VALIDATE_XV_PORT(stuff->port, pPort, DixSetAttrAccess);
684 
685     if (!ValidAtom(stuff->attribute)) {
686         client->errorValue = stuff->attribute;
687         return BadAtom;
688     }
689 
690     status =
691         XvdiSetPortAttribute(client, pPort, stuff->attribute, stuff->value);
692 
693     if (status == BadMatch)
694         client->errorValue = stuff->attribute;
695     else
696         client->errorValue = stuff->value;
697 
698     return status;
699 }
700 
701 static int
ProcXvGetPortAttribute(ClientPtr client)702 ProcXvGetPortAttribute(ClientPtr client)
703 {
704     INT32 value;
705     int status;
706     XvPortPtr pPort;
707     xvGetPortAttributeReply rep;
708 
709     REQUEST(xvGetPortAttributeReq);
710     REQUEST_SIZE_MATCH(xvGetPortAttributeReq);
711 
712     VALIDATE_XV_PORT(stuff->port, pPort, DixGetAttrAccess);
713 
714     if (!ValidAtom(stuff->attribute)) {
715         client->errorValue = stuff->attribute;
716         return BadAtom;
717     }
718 
719     status = XvdiGetPortAttribute(client, pPort, stuff->attribute, &value);
720     if (status != Success) {
721         client->errorValue = stuff->attribute;
722         return status;
723     }
724 
725     rep = (xvGetPortAttributeReply) {
726         .type = X_Reply,
727         .sequenceNumber = client->sequence,
728         .length = 0,
729         .value = value
730     };
731 
732     _WriteGetPortAttributeReply(client, &rep);
733 
734     return Success;
735 }
736 
737 static int
ProcXvQueryBestSize(ClientPtr client)738 ProcXvQueryBestSize(ClientPtr client)
739 {
740     unsigned int actual_width, actual_height;
741     XvPortPtr pPort;
742     xvQueryBestSizeReply rep;
743 
744     REQUEST(xvQueryBestSizeReq);
745     REQUEST_SIZE_MATCH(xvQueryBestSizeReq);
746 
747     VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
748 
749     (*pPort->pAdaptor->ddQueryBestSize) (pPort, stuff->motion,
750                                          stuff->vid_w, stuff->vid_h,
751                                          stuff->drw_w, stuff->drw_h,
752                                          &actual_width, &actual_height);
753 
754     rep = (xvQueryBestSizeReply) {
755         .type = X_Reply,
756         .sequenceNumber = client->sequence,
757         .length = 0,
758         .actual_width = actual_width,
759         .actual_height = actual_height
760     };
761 
762     _WriteQueryBestSizeReply(client, &rep);
763 
764     return Success;
765 }
766 
767 static int
ProcXvQueryPortAttributes(ClientPtr client)768 ProcXvQueryPortAttributes(ClientPtr client)
769 {
770     int size, i;
771     XvPortPtr pPort;
772     XvAttributePtr pAtt;
773     xvQueryPortAttributesReply rep;
774     xvAttributeInfo Info;
775 
776     REQUEST(xvQueryPortAttributesReq);
777     REQUEST_SIZE_MATCH(xvQueryPortAttributesReq);
778 
779     VALIDATE_XV_PORT(stuff->port, pPort, DixGetAttrAccess);
780 
781     rep = (xvQueryPortAttributesReply) {
782         .type = X_Reply,
783         .sequenceNumber = client->sequence,
784         .num_attributes = pPort->pAdaptor->nAttributes,
785         .text_size = 0
786     };
787 
788     for (i = 0, pAtt = pPort->pAdaptor->pAttributes;
789          i < pPort->pAdaptor->nAttributes; i++, pAtt++) {
790         rep.text_size += pad_to_int32(strlen(pAtt->name) + 1);
791     }
792 
793     rep.length = (pPort->pAdaptor->nAttributes * sz_xvAttributeInfo)
794         + rep.text_size;
795     rep.length >>= 2;
796 
797     _WriteQueryPortAttributesReply(client, &rep);
798 
799     for (i = 0, pAtt = pPort->pAdaptor->pAttributes;
800          i < pPort->pAdaptor->nAttributes; i++, pAtt++) {
801         size = strlen(pAtt->name) + 1;  /* pass the NULL */
802         Info.flags = pAtt->flags;
803         Info.min = pAtt->min_value;
804         Info.max = pAtt->max_value;
805         Info.size = pad_to_int32(size);
806 
807         _WriteAttributeInfo(client, &Info);
808 
809         WriteToClient(client, size, pAtt->name);
810     }
811 
812     return Success;
813 }
814 
815 static int
ProcXvPutImage(ClientPtr client)816 ProcXvPutImage(ClientPtr client)
817 {
818     DrawablePtr pDraw;
819     XvPortPtr pPort;
820     XvImagePtr pImage = NULL;
821     GCPtr pGC;
822     int status, i, size;
823     CARD16 width, height;
824 
825     REQUEST(xvPutImageReq);
826     REQUEST_AT_LEAST_SIZE(xvPutImageReq);
827 
828     VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
829     VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
830 
831     if (!(pPort->pAdaptor->type & XvImageMask) ||
832         !(pPort->pAdaptor->type & XvInputMask)) {
833         client->errorValue = stuff->port;
834         return BadMatch;
835     }
836 
837     status = XvdiMatchPort(pPort, pDraw);
838     if (status != Success) {
839         return status;
840     }
841 
842     for (i = 0; i < pPort->pAdaptor->nImages; i++) {
843         if (pPort->pAdaptor->pImages[i].id == stuff->id) {
844             pImage = &(pPort->pAdaptor->pImages[i]);
845             break;
846         }
847     }
848 
849     if (!pImage)
850         return BadMatch;
851 
852     width = stuff->width;
853     height = stuff->height;
854     size = (*pPort->pAdaptor->ddQueryImageAttributes) (pPort, pImage, &width,
855                                                        &height, NULL, NULL);
856     size += sizeof(xvPutImageReq);
857     size = bytes_to_int32(size);
858 
859     if ((width < stuff->width) || (height < stuff->height))
860         return BadValue;
861 
862     if (client->req_len < size)
863         return BadLength;
864 
865     return XvdiPutImage(client, pDraw, pPort, pGC, stuff->src_x, stuff->src_y,
866                         stuff->src_w, stuff->src_h, stuff->drw_x, stuff->drw_y,
867                         stuff->drw_w, stuff->drw_h, pImage,
868                         (unsigned char *) (&stuff[1]), FALSE,
869                         stuff->width, stuff->height);
870 }
871 
872 #ifdef MITSHM
873 
874 static int
ProcXvShmPutImage(ClientPtr client)875 ProcXvShmPutImage(ClientPtr client)
876 {
877     ShmDescPtr shmdesc;
878     DrawablePtr pDraw;
879     XvPortPtr pPort;
880     XvImagePtr pImage = NULL;
881     GCPtr pGC;
882     int status, size_needed, i;
883     CARD16 width, height;
884 
885     REQUEST(xvShmPutImageReq);
886     REQUEST_SIZE_MATCH(xvShmPutImageReq);
887 
888     VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
889     VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
890 
891     if (!(pPort->pAdaptor->type & XvImageMask) ||
892         !(pPort->pAdaptor->type & XvInputMask)) {
893         client->errorValue = stuff->port;
894         return BadMatch;
895     }
896 
897     status = XvdiMatchPort(pPort, pDraw);
898     if (status != Success) {
899         return status;
900     }
901 
902     for (i = 0; i < pPort->pAdaptor->nImages; i++) {
903         if (pPort->pAdaptor->pImages[i].id == stuff->id) {
904             pImage = &(pPort->pAdaptor->pImages[i]);
905             break;
906         }
907     }
908 
909     if (!pImage)
910         return BadMatch;
911 
912     status = dixLookupResourceByType((void **) &shmdesc, stuff->shmseg,
913                                      ShmSegType, serverClient, DixReadAccess);
914     if (status != Success)
915         return status;
916 
917     width = stuff->width;
918     height = stuff->height;
919     size_needed = (*pPort->pAdaptor->ddQueryImageAttributes) (pPort, pImage,
920                                                               &width, &height,
921                                                               NULL, NULL);
922     if ((size_needed + stuff->offset) > shmdesc->size)
923         return BadAccess;
924 
925     if ((width < stuff->width) || (height < stuff->height))
926         return BadValue;
927 
928     status = XvdiPutImage(client, pDraw, pPort, pGC, stuff->src_x, stuff->src_y,
929                           stuff->src_w, stuff->src_h, stuff->drw_x,
930                           stuff->drw_y, stuff->drw_w, stuff->drw_h, pImage,
931                           (unsigned char *) shmdesc->addr + stuff->offset,
932                           stuff->send_event, stuff->width, stuff->height);
933 
934     if ((status == Success) && stuff->send_event) {
935         xShmCompletionEvent ev = {
936             .type = ShmCompletionCode,
937             .drawable = stuff->drawable,
938             .minorEvent = xv_ShmPutImage,
939             .majorEvent = XvReqCode,
940             .shmseg = stuff->shmseg,
941             .offset = stuff->offset
942         };
943         WriteEventsToClient(client, 1, (xEvent *) &ev);
944     }
945 
946     return status;
947 }
948 #else                           /* !MITSHM */
949 static int
ProcXvShmPutImage(ClientPtr client)950 ProcXvShmPutImage(ClientPtr client)
951 {
952     return BadImplementation;
953 }
954 #endif
955 
956 #ifdef XvMCExtension
957 #include "xvmcext.h"
958 #endif
959 
960 static int
ProcXvQueryImageAttributes(ClientPtr client)961 ProcXvQueryImageAttributes(ClientPtr client)
962 {
963     xvQueryImageAttributesReply rep;
964     int size, num_planes, i;
965     CARD16 width, height;
966     XvImagePtr pImage = NULL;
967     XvPortPtr pPort;
968     int *offsets;
969     int *pitches;
970     int planeLength;
971 
972     REQUEST(xvQueryImageAttributesReq);
973 
974     REQUEST_SIZE_MATCH(xvQueryImageAttributesReq);
975 
976     VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
977 
978     for (i = 0; i < pPort->pAdaptor->nImages; i++) {
979         if (pPort->pAdaptor->pImages[i].id == stuff->id) {
980             pImage = &(pPort->pAdaptor->pImages[i]);
981             break;
982         }
983     }
984 
985 #ifdef XvMCExtension
986     if (!pImage)
987         pImage = XvMCFindXvImage(pPort, stuff->id);
988 #endif
989 
990     if (!pImage)
991         return BadMatch;
992 
993     num_planes = pImage->num_planes;
994 
995     if (!(offsets = malloc(num_planes << 3)))
996         return BadAlloc;
997     pitches = offsets + num_planes;
998 
999     width = stuff->width;
1000     height = stuff->height;
1001 
1002     size = (*pPort->pAdaptor->ddQueryImageAttributes) (pPort, pImage,
1003                                                        &width, &height, offsets,
1004                                                        pitches);
1005 
1006     rep = (xvQueryImageAttributesReply) {
1007         .type = X_Reply,
1008         .sequenceNumber = client->sequence,
1009         .length = planeLength = num_planes << 1,
1010         .num_planes = num_planes,
1011         .width = width,
1012         .height = height,
1013         .data_size = size
1014     };
1015 
1016     _WriteQueryImageAttributesReply(client, &rep);
1017     if (client->swapped)
1018         SwapLongs((CARD32 *) offsets, planeLength);
1019     WriteToClient(client, planeLength << 2, offsets);
1020 
1021     free(offsets);
1022 
1023     return Success;
1024 }
1025 
1026 static int
ProcXvListImageFormats(ClientPtr client)1027 ProcXvListImageFormats(ClientPtr client)
1028 {
1029     XvPortPtr pPort;
1030     XvImagePtr pImage;
1031     int i;
1032     xvListImageFormatsReply rep;
1033     xvImageFormatInfo info;
1034 
1035     REQUEST(xvListImageFormatsReq);
1036 
1037     REQUEST_SIZE_MATCH(xvListImageFormatsReq);
1038 
1039     VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
1040 
1041     rep = (xvListImageFormatsReply) {
1042         .type = X_Reply,
1043         .sequenceNumber = client->sequence,
1044         .num_formats = pPort->pAdaptor->nImages,
1045         .length =
1046             bytes_to_int32(pPort->pAdaptor->nImages * sz_xvImageFormatInfo)
1047     };
1048 
1049     _WriteListImageFormatsReply(client, &rep);
1050 
1051     pImage = pPort->pAdaptor->pImages;
1052 
1053     for (i = 0; i < pPort->pAdaptor->nImages; i++, pImage++) {
1054         info.id = pImage->id;
1055         info.type = pImage->type;
1056         info.byte_order = pImage->byte_order;
1057         memcpy(&info.guid, pImage->guid, 16);
1058         info.bpp = pImage->bits_per_pixel;
1059         info.num_planes = pImage->num_planes;
1060         info.depth = pImage->depth;
1061         info.red_mask = pImage->red_mask;
1062         info.green_mask = pImage->green_mask;
1063         info.blue_mask = pImage->blue_mask;
1064         info.format = pImage->format;
1065         info.y_sample_bits = pImage->y_sample_bits;
1066         info.u_sample_bits = pImage->u_sample_bits;
1067         info.v_sample_bits = pImage->v_sample_bits;
1068         info.horz_y_period = pImage->horz_y_period;
1069         info.horz_u_period = pImage->horz_u_period;
1070         info.horz_v_period = pImage->horz_v_period;
1071         info.vert_y_period = pImage->vert_y_period;
1072         info.vert_u_period = pImage->vert_u_period;
1073         info.vert_v_period = pImage->vert_v_period;
1074         memcpy(&info.comp_order, pImage->component_order, 32);
1075         info.scanline_order = pImage->scanline_order;
1076         _WriteImageFormatInfo(client, &info);
1077     }
1078 
1079     return Success;
1080 }
1081 
1082 static int (*XvProcVector[xvNumRequests]) (ClientPtr) = {
1083 ProcXvQueryExtension,
1084         ProcXvQueryAdaptors,
1085         ProcXvQueryEncodings,
1086         ProcXvGrabPort,
1087         ProcXvUngrabPort,
1088         ProcXvPutVideo,
1089         ProcXvPutStill,
1090         ProcXvGetVideo,
1091         ProcXvGetStill,
1092         ProcXvStopVideo,
1093         ProcXvSelectVideoNotify,
1094         ProcXvSelectPortNotify,
1095         ProcXvQueryBestSize,
1096         ProcXvSetPortAttribute,
1097         ProcXvGetPortAttribute,
1098         ProcXvQueryPortAttributes,
1099         ProcXvListImageFormats,
1100         ProcXvQueryImageAttributes, ProcXvPutImage, ProcXvShmPutImage,};
1101 
1102 int
ProcXvDispatch(ClientPtr client)1103 ProcXvDispatch(ClientPtr client)
1104 {
1105     REQUEST(xReq);
1106 
1107     UpdateCurrentTime();
1108 
1109     if (stuff->data >= xvNumRequests) {
1110         return BadRequest;
1111     }
1112 
1113     return XvProcVector[stuff->data] (client);
1114 }
1115 
1116 /* Swapped Procs */
1117 
1118 static int _X_COLD
SProcXvQueryExtension(ClientPtr client)1119 SProcXvQueryExtension(ClientPtr client)
1120 {
1121     REQUEST(xvQueryExtensionReq);
1122     REQUEST_SIZE_MATCH(xvQueryExtensionReq);
1123     swaps(&stuff->length);
1124     return XvProcVector[xv_QueryExtension] (client);
1125 }
1126 
1127 static int _X_COLD
SProcXvQueryAdaptors(ClientPtr client)1128 SProcXvQueryAdaptors(ClientPtr client)
1129 {
1130     REQUEST(xvQueryAdaptorsReq);
1131     REQUEST_SIZE_MATCH(xvQueryAdaptorsReq);
1132     swaps(&stuff->length);
1133     swapl(&stuff->window);
1134     return XvProcVector[xv_QueryAdaptors] (client);
1135 }
1136 
1137 static int _X_COLD
SProcXvQueryEncodings(ClientPtr client)1138 SProcXvQueryEncodings(ClientPtr client)
1139 {
1140     REQUEST(xvQueryEncodingsReq);
1141     REQUEST_SIZE_MATCH(xvQueryEncodingsReq);
1142     swaps(&stuff->length);
1143     swapl(&stuff->port);
1144     return XvProcVector[xv_QueryEncodings] (client);
1145 }
1146 
1147 static int _X_COLD
SProcXvGrabPort(ClientPtr client)1148 SProcXvGrabPort(ClientPtr client)
1149 {
1150     REQUEST(xvGrabPortReq);
1151     REQUEST_SIZE_MATCH(xvGrabPortReq);
1152     swaps(&stuff->length);
1153     swapl(&stuff->port);
1154     swapl(&stuff->time);
1155     return XvProcVector[xv_GrabPort] (client);
1156 }
1157 
1158 static int _X_COLD
SProcXvUngrabPort(ClientPtr client)1159 SProcXvUngrabPort(ClientPtr client)
1160 {
1161     REQUEST(xvUngrabPortReq);
1162     REQUEST_SIZE_MATCH(xvUngrabPortReq);
1163     swaps(&stuff->length);
1164     swapl(&stuff->port);
1165     swapl(&stuff->time);
1166     return XvProcVector[xv_UngrabPort] (client);
1167 }
1168 
1169 static int _X_COLD
SProcXvPutVideo(ClientPtr client)1170 SProcXvPutVideo(ClientPtr client)
1171 {
1172     REQUEST(xvPutVideoReq);
1173     REQUEST_SIZE_MATCH(xvPutVideoReq);
1174     swaps(&stuff->length);
1175     swapl(&stuff->port);
1176     swapl(&stuff->drawable);
1177     swapl(&stuff->gc);
1178     swaps(&stuff->vid_x);
1179     swaps(&stuff->vid_y);
1180     swaps(&stuff->vid_w);
1181     swaps(&stuff->vid_h);
1182     swaps(&stuff->drw_x);
1183     swaps(&stuff->drw_y);
1184     swaps(&stuff->drw_w);
1185     swaps(&stuff->drw_h);
1186     return XvProcVector[xv_PutVideo] (client);
1187 }
1188 
1189 static int _X_COLD
SProcXvPutStill(ClientPtr client)1190 SProcXvPutStill(ClientPtr client)
1191 {
1192     REQUEST(xvPutStillReq);
1193     REQUEST_SIZE_MATCH(xvPutStillReq);
1194     swaps(&stuff->length);
1195     swapl(&stuff->port);
1196     swapl(&stuff->drawable);
1197     swapl(&stuff->gc);
1198     swaps(&stuff->vid_x);
1199     swaps(&stuff->vid_y);
1200     swaps(&stuff->vid_w);
1201     swaps(&stuff->vid_h);
1202     swaps(&stuff->drw_x);
1203     swaps(&stuff->drw_y);
1204     swaps(&stuff->drw_w);
1205     swaps(&stuff->drw_h);
1206     return XvProcVector[xv_PutStill] (client);
1207 }
1208 
1209 static int _X_COLD
SProcXvGetVideo(ClientPtr client)1210 SProcXvGetVideo(ClientPtr client)
1211 {
1212     REQUEST(xvGetVideoReq);
1213     REQUEST_SIZE_MATCH(xvGetVideoReq);
1214     swaps(&stuff->length);
1215     swapl(&stuff->port);
1216     swapl(&stuff->drawable);
1217     swapl(&stuff->gc);
1218     swaps(&stuff->vid_x);
1219     swaps(&stuff->vid_y);
1220     swaps(&stuff->vid_w);
1221     swaps(&stuff->vid_h);
1222     swaps(&stuff->drw_x);
1223     swaps(&stuff->drw_y);
1224     swaps(&stuff->drw_w);
1225     swaps(&stuff->drw_h);
1226     return XvProcVector[xv_GetVideo] (client);
1227 }
1228 
1229 static int _X_COLD
SProcXvGetStill(ClientPtr client)1230 SProcXvGetStill(ClientPtr client)
1231 {
1232     REQUEST(xvGetStillReq);
1233     REQUEST_SIZE_MATCH(xvGetStillReq);
1234     swaps(&stuff->length);
1235     swapl(&stuff->port);
1236     swapl(&stuff->drawable);
1237     swapl(&stuff->gc);
1238     swaps(&stuff->vid_x);
1239     swaps(&stuff->vid_y);
1240     swaps(&stuff->vid_w);
1241     swaps(&stuff->vid_h);
1242     swaps(&stuff->drw_x);
1243     swaps(&stuff->drw_y);
1244     swaps(&stuff->drw_w);
1245     swaps(&stuff->drw_h);
1246     return XvProcVector[xv_GetStill] (client);
1247 }
1248 
1249 static int _X_COLD
SProcXvPutImage(ClientPtr client)1250 SProcXvPutImage(ClientPtr client)
1251 {
1252     REQUEST(xvPutImageReq);
1253     REQUEST_AT_LEAST_SIZE(xvPutImageReq);
1254     swaps(&stuff->length);
1255     swapl(&stuff->port);
1256     swapl(&stuff->drawable);
1257     swapl(&stuff->gc);
1258     swapl(&stuff->id);
1259     swaps(&stuff->src_x);
1260     swaps(&stuff->src_y);
1261     swaps(&stuff->src_w);
1262     swaps(&stuff->src_h);
1263     swaps(&stuff->drw_x);
1264     swaps(&stuff->drw_y);
1265     swaps(&stuff->drw_w);
1266     swaps(&stuff->drw_h);
1267     swaps(&stuff->width);
1268     swaps(&stuff->height);
1269     return XvProcVector[xv_PutImage] (client);
1270 }
1271 
1272 #ifdef MITSHM
1273 static int _X_COLD
SProcXvShmPutImage(ClientPtr client)1274 SProcXvShmPutImage(ClientPtr client)
1275 {
1276     REQUEST(xvShmPutImageReq);
1277     REQUEST_SIZE_MATCH(xvShmPutImageReq);
1278     swaps(&stuff->length);
1279     swapl(&stuff->port);
1280     swapl(&stuff->drawable);
1281     swapl(&stuff->gc);
1282     swapl(&stuff->shmseg);
1283     swapl(&stuff->id);
1284     swapl(&stuff->offset);
1285     swaps(&stuff->src_x);
1286     swaps(&stuff->src_y);
1287     swaps(&stuff->src_w);
1288     swaps(&stuff->src_h);
1289     swaps(&stuff->drw_x);
1290     swaps(&stuff->drw_y);
1291     swaps(&stuff->drw_w);
1292     swaps(&stuff->drw_h);
1293     swaps(&stuff->width);
1294     swaps(&stuff->height);
1295     return XvProcVector[xv_ShmPutImage] (client);
1296 }
1297 #else                           /* MITSHM */
1298 #define SProcXvShmPutImage ProcXvShmPutImage
1299 #endif
1300 
1301 static int _X_COLD
SProcXvSelectVideoNotify(ClientPtr client)1302 SProcXvSelectVideoNotify(ClientPtr client)
1303 {
1304     REQUEST(xvSelectVideoNotifyReq);
1305     REQUEST_SIZE_MATCH(xvSelectVideoNotifyReq);
1306     swaps(&stuff->length);
1307     swapl(&stuff->drawable);
1308     return XvProcVector[xv_SelectVideoNotify] (client);
1309 }
1310 
1311 static int _X_COLD
SProcXvSelectPortNotify(ClientPtr client)1312 SProcXvSelectPortNotify(ClientPtr client)
1313 {
1314     REQUEST(xvSelectPortNotifyReq);
1315     REQUEST_SIZE_MATCH(xvSelectPortNotifyReq);
1316     swaps(&stuff->length);
1317     swapl(&stuff->port);
1318     return XvProcVector[xv_SelectPortNotify] (client);
1319 }
1320 
1321 static int _X_COLD
SProcXvStopVideo(ClientPtr client)1322 SProcXvStopVideo(ClientPtr client)
1323 {
1324     REQUEST(xvStopVideoReq);
1325     REQUEST_SIZE_MATCH(xvStopVideoReq);
1326     swaps(&stuff->length);
1327     swapl(&stuff->port);
1328     swapl(&stuff->drawable);
1329     return XvProcVector[xv_StopVideo] (client);
1330 }
1331 
1332 static int _X_COLD
SProcXvSetPortAttribute(ClientPtr client)1333 SProcXvSetPortAttribute(ClientPtr client)
1334 {
1335     REQUEST(xvSetPortAttributeReq);
1336     REQUEST_SIZE_MATCH(xvSetPortAttributeReq);
1337     swaps(&stuff->length);
1338     swapl(&stuff->port);
1339     swapl(&stuff->attribute);
1340     swapl(&stuff->value);
1341     return XvProcVector[xv_SetPortAttribute] (client);
1342 }
1343 
1344 static int _X_COLD
SProcXvGetPortAttribute(ClientPtr client)1345 SProcXvGetPortAttribute(ClientPtr client)
1346 {
1347     REQUEST(xvGetPortAttributeReq);
1348     REQUEST_SIZE_MATCH(xvGetPortAttributeReq);
1349     swaps(&stuff->length);
1350     swapl(&stuff->port);
1351     swapl(&stuff->attribute);
1352     return XvProcVector[xv_GetPortAttribute] (client);
1353 }
1354 
1355 static int _X_COLD
SProcXvQueryBestSize(ClientPtr client)1356 SProcXvQueryBestSize(ClientPtr client)
1357 {
1358     REQUEST(xvQueryBestSizeReq);
1359     REQUEST_SIZE_MATCH(xvQueryBestSizeReq);
1360     swaps(&stuff->length);
1361     swapl(&stuff->port);
1362     swaps(&stuff->vid_w);
1363     swaps(&stuff->vid_h);
1364     swaps(&stuff->drw_w);
1365     swaps(&stuff->drw_h);
1366     return XvProcVector[xv_QueryBestSize] (client);
1367 }
1368 
1369 static int _X_COLD
SProcXvQueryPortAttributes(ClientPtr client)1370 SProcXvQueryPortAttributes(ClientPtr client)
1371 {
1372     REQUEST(xvQueryPortAttributesReq);
1373     REQUEST_SIZE_MATCH(xvQueryPortAttributesReq);
1374     swaps(&stuff->length);
1375     swapl(&stuff->port);
1376     return XvProcVector[xv_QueryPortAttributes] (client);
1377 }
1378 
1379 static int _X_COLD
SProcXvQueryImageAttributes(ClientPtr client)1380 SProcXvQueryImageAttributes(ClientPtr client)
1381 {
1382     REQUEST(xvQueryImageAttributesReq);
1383     REQUEST_SIZE_MATCH(xvQueryImageAttributesReq);
1384     swaps(&stuff->length);
1385     swapl(&stuff->port);
1386     swapl(&stuff->id);
1387     swaps(&stuff->width);
1388     swaps(&stuff->height);
1389     return XvProcVector[xv_QueryImageAttributes] (client);
1390 }
1391 
1392 static int _X_COLD
SProcXvListImageFormats(ClientPtr client)1393 SProcXvListImageFormats(ClientPtr client)
1394 {
1395     REQUEST(xvListImageFormatsReq);
1396     REQUEST_SIZE_MATCH(xvListImageFormatsReq);
1397     swaps(&stuff->length);
1398     swapl(&stuff->port);
1399     return XvProcVector[xv_ListImageFormats] (client);
1400 }
1401 
1402 static int (*SXvProcVector[xvNumRequests]) (ClientPtr) = {
1403 SProcXvQueryExtension,
1404         SProcXvQueryAdaptors,
1405         SProcXvQueryEncodings,
1406         SProcXvGrabPort,
1407         SProcXvUngrabPort,
1408         SProcXvPutVideo,
1409         SProcXvPutStill,
1410         SProcXvGetVideo,
1411         SProcXvGetStill,
1412         SProcXvStopVideo,
1413         SProcXvSelectVideoNotify,
1414         SProcXvSelectPortNotify,
1415         SProcXvQueryBestSize,
1416         SProcXvSetPortAttribute,
1417         SProcXvGetPortAttribute,
1418         SProcXvQueryPortAttributes,
1419         SProcXvListImageFormats,
1420         SProcXvQueryImageAttributes, SProcXvPutImage, SProcXvShmPutImage,};
1421 
1422 int _X_COLD
SProcXvDispatch(ClientPtr client)1423 SProcXvDispatch(ClientPtr client)
1424 {
1425     REQUEST(xReq);
1426 
1427     UpdateCurrentTime();
1428 
1429     if (stuff->data >= xvNumRequests) {
1430         return BadRequest;
1431     }
1432 
1433     return SXvProcVector[stuff->data] (client);
1434 }
1435 
1436 #ifdef PANORAMIX
1437 static int
XineramaXvStopVideo(ClientPtr client)1438 XineramaXvStopVideo(ClientPtr client)
1439 {
1440     int result, i;
1441     PanoramiXRes *draw, *port;
1442 
1443     REQUEST(xvStopVideoReq);
1444     REQUEST_SIZE_MATCH(xvStopVideoReq);
1445 
1446     result = dixLookupResourceByClass((void **) &draw, stuff->drawable,
1447                                       XRC_DRAWABLE, client, DixWriteAccess);
1448     if (result != Success)
1449         return (result == BadValue) ? BadDrawable : result;
1450 
1451     result = dixLookupResourceByType((void **) &port, stuff->port,
1452                                      XvXRTPort, client, DixReadAccess);
1453     if (result != Success)
1454         return result;
1455 
1456     FOR_NSCREENS_BACKWARD(i) {
1457         if (port->info[i].id) {
1458             stuff->drawable = draw->info[i].id;
1459             stuff->port = port->info[i].id;
1460             result = ProcXvStopVideo(client);
1461         }
1462     }
1463 
1464     return result;
1465 }
1466 
1467 static int
XineramaXvSetPortAttribute(ClientPtr client)1468 XineramaXvSetPortAttribute(ClientPtr client)
1469 {
1470     REQUEST(xvSetPortAttributeReq);
1471     PanoramiXRes *port;
1472     int result, i;
1473 
1474     REQUEST_SIZE_MATCH(xvSetPortAttributeReq);
1475 
1476     result = dixLookupResourceByType((void **) &port, stuff->port,
1477                                      XvXRTPort, client, DixReadAccess);
1478     if (result != Success)
1479         return result;
1480 
1481     FOR_NSCREENS_BACKWARD(i) {
1482         if (port->info[i].id) {
1483             stuff->port = port->info[i].id;
1484             result = ProcXvSetPortAttribute(client);
1485         }
1486     }
1487     return result;
1488 }
1489 
1490 #ifdef MITSHM
1491 static int
XineramaXvShmPutImage(ClientPtr client)1492 XineramaXvShmPutImage(ClientPtr client)
1493 {
1494     REQUEST(xvShmPutImageReq);
1495     PanoramiXRes *draw, *gc, *port;
1496     Bool send_event;
1497     Bool isRoot;
1498     int result, i, x, y;
1499 
1500     REQUEST_SIZE_MATCH(xvShmPutImageReq);
1501 
1502     send_event = stuff->send_event;
1503 
1504     result = dixLookupResourceByClass((void **) &draw, stuff->drawable,
1505                                       XRC_DRAWABLE, client, DixWriteAccess);
1506     if (result != Success)
1507         return (result == BadValue) ? BadDrawable : result;
1508 
1509     result = dixLookupResourceByType((void **) &gc, stuff->gc,
1510                                      XRT_GC, client, DixReadAccess);
1511     if (result != Success)
1512         return result;
1513 
1514     result = dixLookupResourceByType((void **) &port, stuff->port,
1515                                      XvXRTPort, client, DixReadAccess);
1516     if (result != Success)
1517         return result;
1518 
1519     isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
1520 
1521     x = stuff->drw_x;
1522     y = stuff->drw_y;
1523 
1524     FOR_NSCREENS_BACKWARD(i) {
1525         if (port->info[i].id) {
1526             stuff->drawable = draw->info[i].id;
1527             stuff->port = port->info[i].id;
1528             stuff->gc = gc->info[i].id;
1529             stuff->drw_x = x;
1530             stuff->drw_y = y;
1531             if (isRoot) {
1532                 stuff->drw_x -= screenInfo.screens[i]->x;
1533                 stuff->drw_y -= screenInfo.screens[i]->y;
1534             }
1535             stuff->send_event = (send_event && !i) ? 1 : 0;
1536 
1537             result = ProcXvShmPutImage(client);
1538         }
1539     }
1540     return result;
1541 }
1542 #else
1543 #define XineramaXvShmPutImage ProcXvShmPutImage
1544 #endif
1545 
1546 static int
XineramaXvPutImage(ClientPtr client)1547 XineramaXvPutImage(ClientPtr client)
1548 {
1549     REQUEST(xvPutImageReq);
1550     PanoramiXRes *draw, *gc, *port;
1551     Bool isRoot;
1552     int result, i, x, y;
1553 
1554     REQUEST_AT_LEAST_SIZE(xvPutImageReq);
1555 
1556     result = dixLookupResourceByClass((void **) &draw, stuff->drawable,
1557                                       XRC_DRAWABLE, client, DixWriteAccess);
1558     if (result != Success)
1559         return (result == BadValue) ? BadDrawable : result;
1560 
1561     result = dixLookupResourceByType((void **) &gc, stuff->gc,
1562                                      XRT_GC, client, DixReadAccess);
1563     if (result != Success)
1564         return result;
1565 
1566     result = dixLookupResourceByType((void **) &port, stuff->port,
1567                                      XvXRTPort, client, DixReadAccess);
1568     if (result != Success)
1569         return result;
1570 
1571     isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
1572 
1573     x = stuff->drw_x;
1574     y = stuff->drw_y;
1575 
1576     FOR_NSCREENS_BACKWARD(i) {
1577         if (port->info[i].id) {
1578             stuff->drawable = draw->info[i].id;
1579             stuff->port = port->info[i].id;
1580             stuff->gc = gc->info[i].id;
1581             stuff->drw_x = x;
1582             stuff->drw_y = y;
1583             if (isRoot) {
1584                 stuff->drw_x -= screenInfo.screens[i]->x;
1585                 stuff->drw_y -= screenInfo.screens[i]->y;
1586             }
1587 
1588             result = ProcXvPutImage(client);
1589         }
1590     }
1591     return result;
1592 }
1593 
1594 static int
XineramaXvPutVideo(ClientPtr client)1595 XineramaXvPutVideo(ClientPtr client)
1596 {
1597     REQUEST(xvPutImageReq);
1598     PanoramiXRes *draw, *gc, *port;
1599     Bool isRoot;
1600     int result, i, x, y;
1601 
1602     REQUEST_AT_LEAST_SIZE(xvPutVideoReq);
1603 
1604     result = dixLookupResourceByClass((void **) &draw, stuff->drawable,
1605                                       XRC_DRAWABLE, client, DixWriteAccess);
1606     if (result != Success)
1607         return (result == BadValue) ? BadDrawable : result;
1608 
1609     result = dixLookupResourceByType((void **) &gc, stuff->gc,
1610                                      XRT_GC, client, DixReadAccess);
1611     if (result != Success)
1612         return result;
1613 
1614     result = dixLookupResourceByType((void **) &port, stuff->port,
1615                                      XvXRTPort, client, DixReadAccess);
1616     if (result != Success)
1617         return result;
1618 
1619     isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
1620 
1621     x = stuff->drw_x;
1622     y = stuff->drw_y;
1623 
1624     FOR_NSCREENS_BACKWARD(i) {
1625         if (port->info[i].id) {
1626             stuff->drawable = draw->info[i].id;
1627             stuff->port = port->info[i].id;
1628             stuff->gc = gc->info[i].id;
1629             stuff->drw_x = x;
1630             stuff->drw_y = y;
1631             if (isRoot) {
1632                 stuff->drw_x -= screenInfo.screens[i]->x;
1633                 stuff->drw_y -= screenInfo.screens[i]->y;
1634             }
1635 
1636             result = ProcXvPutVideo(client);
1637         }
1638     }
1639     return result;
1640 }
1641 
1642 static int
XineramaXvPutStill(ClientPtr client)1643 XineramaXvPutStill(ClientPtr client)
1644 {
1645     REQUEST(xvPutImageReq);
1646     PanoramiXRes *draw, *gc, *port;
1647     Bool isRoot;
1648     int result, i, x, y;
1649 
1650     REQUEST_AT_LEAST_SIZE(xvPutImageReq);
1651 
1652     result = dixLookupResourceByClass((void **) &draw, stuff->drawable,
1653                                       XRC_DRAWABLE, client, DixWriteAccess);
1654     if (result != Success)
1655         return (result == BadValue) ? BadDrawable : result;
1656 
1657     result = dixLookupResourceByType((void **) &gc, stuff->gc,
1658                                      XRT_GC, client, DixReadAccess);
1659     if (result != Success)
1660         return result;
1661 
1662     result = dixLookupResourceByType((void **) &port, stuff->port,
1663                                      XvXRTPort, client, DixReadAccess);
1664     if (result != Success)
1665         return result;
1666 
1667     isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
1668 
1669     x = stuff->drw_x;
1670     y = stuff->drw_y;
1671 
1672     FOR_NSCREENS_BACKWARD(i) {
1673         if (port->info[i].id) {
1674             stuff->drawable = draw->info[i].id;
1675             stuff->port = port->info[i].id;
1676             stuff->gc = gc->info[i].id;
1677             stuff->drw_x = x;
1678             stuff->drw_y = y;
1679             if (isRoot) {
1680                 stuff->drw_x -= screenInfo.screens[i]->x;
1681                 stuff->drw_y -= screenInfo.screens[i]->y;
1682             }
1683 
1684             result = ProcXvPutStill(client);
1685         }
1686     }
1687     return result;
1688 }
1689 
1690 static Bool
isImageAdaptor(XvAdaptorPtr pAdapt)1691 isImageAdaptor(XvAdaptorPtr pAdapt)
1692 {
1693     return (pAdapt->type & XvImageMask) && (pAdapt->nImages > 0);
1694 }
1695 
1696 static Bool
hasOverlay(XvAdaptorPtr pAdapt)1697 hasOverlay(XvAdaptorPtr pAdapt)
1698 {
1699     int i;
1700 
1701     for (i = 0; i < pAdapt->nAttributes; i++)
1702         if (!strcmp(pAdapt->pAttributes[i].name, "XV_COLORKEY"))
1703             return TRUE;
1704     return FALSE;
1705 }
1706 
1707 static XvAdaptorPtr
matchAdaptor(ScreenPtr pScreen,XvAdaptorPtr refAdapt,Bool isOverlay)1708 matchAdaptor(ScreenPtr pScreen, XvAdaptorPtr refAdapt, Bool isOverlay)
1709 {
1710     int i;
1711     XvScreenPtr xvsp =
1712         dixLookupPrivate(&pScreen->devPrivates, XvGetScreenKey());
1713     /* Do not try to go on if xv is not supported on this screen */
1714     if (xvsp == NULL)
1715         return NULL;
1716 
1717     /* if the adaptor has the same name it's a perfect match */
1718     for (i = 0; i < xvsp->nAdaptors; i++) {
1719         XvAdaptorPtr pAdapt = xvsp->pAdaptors + i;
1720 
1721         if (!strcmp(refAdapt->name, pAdapt->name))
1722             return pAdapt;
1723     }
1724 
1725     /* otherwise we only look for XvImage adaptors */
1726     if (!isImageAdaptor(refAdapt))
1727         return NULL;
1728 
1729     /* prefer overlay/overlay non-overlay/non-overlay pairing */
1730     for (i = 0; i < xvsp->nAdaptors; i++) {
1731         XvAdaptorPtr pAdapt = xvsp->pAdaptors + i;
1732 
1733         if (isImageAdaptor(pAdapt) && isOverlay == hasOverlay(pAdapt))
1734             return pAdapt;
1735     }
1736 
1737     /* but we'll take any XvImage pairing if we can get it */
1738     for (i = 0; i < xvsp->nAdaptors; i++) {
1739         XvAdaptorPtr pAdapt = xvsp->pAdaptors + i;
1740 
1741         if (isImageAdaptor(pAdapt))
1742             return pAdapt;
1743     }
1744     return NULL;
1745 }
1746 
1747 void
XineramifyXv(void)1748 XineramifyXv(void)
1749 {
1750     XvScreenPtr xvsp0 =
1751         dixLookupPrivate(&screenInfo.screens[0]->devPrivates, XvGetScreenKey());
1752     XvAdaptorPtr MatchingAdaptors[MAXSCREENS];
1753     int i, j, k;
1754 
1755     XvXRTPort = CreateNewResourceType(XineramaDeleteResource, "XvXRTPort");
1756 
1757     if (!xvsp0 || !XvXRTPort)
1758         return;
1759     SetResourceTypeErrorValue(XvXRTPort, _XvBadPort);
1760 
1761     for (i = 0; i < xvsp0->nAdaptors; i++) {
1762         Bool isOverlay;
1763         XvAdaptorPtr refAdapt = xvsp0->pAdaptors + i;
1764 
1765         if (!(refAdapt->type & XvInputMask))
1766             continue;
1767 
1768         MatchingAdaptors[0] = refAdapt;
1769         isOverlay = hasOverlay(refAdapt);
1770         FOR_NSCREENS_FORWARD_SKIP(j)
1771             MatchingAdaptors[j] =
1772             matchAdaptor(screenInfo.screens[j], refAdapt, isOverlay);
1773 
1774         /* now create a resource for each port */
1775         for (j = 0; j < refAdapt->nPorts; j++) {
1776             PanoramiXRes *port = malloc(sizeof(PanoramiXRes));
1777 
1778             if (!port)
1779                 break;
1780 
1781             FOR_NSCREENS(k) {
1782                 if (MatchingAdaptors[k] && (MatchingAdaptors[k]->nPorts > j))
1783                     port->info[k].id = MatchingAdaptors[k]->base_id + j;
1784                 else
1785                     port->info[k].id = 0;
1786             }
1787             AddResource(port->info[0].id, XvXRTPort, port);
1788         }
1789     }
1790 
1791     /* munge the dispatch vector */
1792     XvProcVector[xv_PutVideo] = XineramaXvPutVideo;
1793     XvProcVector[xv_PutStill] = XineramaXvPutStill;
1794     XvProcVector[xv_StopVideo] = XineramaXvStopVideo;
1795     XvProcVector[xv_SetPortAttribute] = XineramaXvSetPortAttribute;
1796     XvProcVector[xv_PutImage] = XineramaXvPutImage;
1797     XvProcVector[xv_ShmPutImage] = XineramaXvShmPutImage;
1798 }
1799 #endif                          /* PANORAMIX */
1800 
1801 void
XvResetProcVector(void)1802 XvResetProcVector(void)
1803 {
1804 #ifdef PANORAMIX
1805     XvProcVector[xv_PutVideo] = ProcXvPutVideo;
1806     XvProcVector[xv_PutStill] = ProcXvPutStill;
1807     XvProcVector[xv_StopVideo] = ProcXvStopVideo;
1808     XvProcVector[xv_SetPortAttribute] = ProcXvSetPortAttribute;
1809     XvProcVector[xv_PutImage] = ProcXvPutImage;
1810     XvProcVector[xv_ShmPutImage] = ProcXvShmPutImage;
1811 #endif
1812 }
1813