xvdisp.c revision 7e31ba66
1/***********************************************************
2Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts,
3and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
4
5                        All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Digital or MIT not be
12used in advertising or publicity pertaining to distribution of the
13software without specific, written prior permission.
14
15DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
16ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
17DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21SOFTWARE.
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
55unsigned long XvXRTPort;
56#endif
57
58static int
59SWriteQueryExtensionReply(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
71static int
72SWriteQueryAdaptorsReply(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
83static int
84SWriteQueryEncodingsReply(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
95static int
96SWriteAdaptorInfo(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
108static int
109SWriteEncodingInfo(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
123static int
124SWriteFormat(ClientPtr client, xvFormat * pFormat)
125{
126    swapl(&pFormat->visual);
127    WriteToClient(client, sz_xvFormat, pFormat);
128
129    return Success;
130}
131
132static int
133SWriteAttributeInfo(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
144static int
145SWriteImageFormatInfo(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
166static int
167SWriteGrabPortReply(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
177static int
178SWriteGetPortAttributeReply(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
189static int
190SWriteQueryBestSizeReply(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
202static int
203SWriteQueryPortAttributesReply(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
216static int
217SWriteQueryImageAttributesReply(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
232static int
233SWriteListImageFormatsReply(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
300static int
301ProcXvQueryExtension(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
319static int
320ProcXvQueryAdaptors(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
410static int
411ProcXvQueryEncodings(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
463static int
464ProcXvPutVideo(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
493static int
494ProcXvPutStill(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
523static int
524ProcXvGetVideo(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
553static int
554ProcXvGetStill(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
583static int
584ProcXvSelectVideoNotify(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
600static int
601ProcXvSelectPortNotify(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
613static int
614ProcXvGrabPort(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
642static int
643ProcXvUngrabPort(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
655static int
656ProcXvStopVideo(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
674static int
675ProcXvSetPortAttribute(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
701static int
702ProcXvGetPortAttribute(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
737static int
738ProcXvQueryBestSize(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
767static int
768ProcXvQueryPortAttributes(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
815static int
816ProcXvPutImage(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
874static int
875ProcXvShmPutImage(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 */
949static int
950ProcXvShmPutImage(ClientPtr client)
951{
952    return BadImplementation;
953}
954#endif
955
956#ifdef XvMCExtension
957#include "xvmcext.h"
958#endif
959
960static int
961ProcXvQueryImageAttributes(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
1026static int
1027ProcXvListImageFormats(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
1082static int (*XvProcVector[xvNumRequests]) (ClientPtr) = {
1083ProcXvQueryExtension,
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
1102int
1103ProcXvDispatch(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
1118static int _X_COLD
1119SProcXvQueryExtension(ClientPtr client)
1120{
1121    REQUEST(xvQueryExtensionReq);
1122    REQUEST_SIZE_MATCH(xvQueryExtensionReq);
1123    swaps(&stuff->length);
1124    return XvProcVector[xv_QueryExtension] (client);
1125}
1126
1127static int _X_COLD
1128SProcXvQueryAdaptors(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
1137static int _X_COLD
1138SProcXvQueryEncodings(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
1147static int _X_COLD
1148SProcXvGrabPort(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
1158static int _X_COLD
1159SProcXvUngrabPort(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
1169static int _X_COLD
1170SProcXvPutVideo(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
1189static int _X_COLD
1190SProcXvPutStill(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
1209static int _X_COLD
1210SProcXvGetVideo(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
1229static int _X_COLD
1230SProcXvGetStill(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
1249static int _X_COLD
1250SProcXvPutImage(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
1273static int _X_COLD
1274SProcXvShmPutImage(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
1301static int _X_COLD
1302SProcXvSelectVideoNotify(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
1311static int _X_COLD
1312SProcXvSelectPortNotify(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
1321static int _X_COLD
1322SProcXvStopVideo(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
1332static int _X_COLD
1333SProcXvSetPortAttribute(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
1344static int _X_COLD
1345SProcXvGetPortAttribute(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
1355static int _X_COLD
1356SProcXvQueryBestSize(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
1369static int _X_COLD
1370SProcXvQueryPortAttributes(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
1379static int _X_COLD
1380SProcXvQueryImageAttributes(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
1392static int _X_COLD
1393SProcXvListImageFormats(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
1402static int (*SXvProcVector[xvNumRequests]) (ClientPtr) = {
1403SProcXvQueryExtension,
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
1422int _X_COLD
1423SProcXvDispatch(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
1437static int
1438XineramaXvStopVideo(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
1467static int
1468XineramaXvSetPortAttribute(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
1491static int
1492XineramaXvShmPutImage(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
1546static int
1547XineramaXvPutImage(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
1594static int
1595XineramaXvPutVideo(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
1642static int
1643XineramaXvPutStill(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
1690static Bool
1691isImageAdaptor(XvAdaptorPtr pAdapt)
1692{
1693    return (pAdapt->type & XvImageMask) && (pAdapt->nImages > 0);
1694}
1695
1696static Bool
1697hasOverlay(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
1707static XvAdaptorPtr
1708matchAdaptor(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
1747void
1748XineramifyXv(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
1801void
1802XvResetProcVector(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