xvdisp.c revision f7df2e56
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    SendErrorToClient(client, XvReqCode, xv_ShmPutImage, 0, BadImplementation);
953    return BadImplementation;
954}
955#endif
956
957#ifdef XvMCExtension
958#include "xvmcext.h"
959#endif
960
961static int
962ProcXvQueryImageAttributes(ClientPtr client)
963{
964    xvQueryImageAttributesReply rep;
965    int size, num_planes, i;
966    CARD16 width, height;
967    XvImagePtr pImage = NULL;
968    XvPortPtr pPort;
969    int *offsets;
970    int *pitches;
971    int planeLength;
972
973    REQUEST(xvQueryImageAttributesReq);
974
975    REQUEST_SIZE_MATCH(xvQueryImageAttributesReq);
976
977    VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
978
979    for (i = 0; i < pPort->pAdaptor->nImages; i++) {
980        if (pPort->pAdaptor->pImages[i].id == stuff->id) {
981            pImage = &(pPort->pAdaptor->pImages[i]);
982            break;
983        }
984    }
985
986#ifdef XvMCExtension
987    if (!pImage)
988        pImage = XvMCFindXvImage(pPort, stuff->id);
989#endif
990
991    if (!pImage)
992        return BadMatch;
993
994    num_planes = pImage->num_planes;
995
996    if (!(offsets = malloc(num_planes << 3)))
997        return BadAlloc;
998    pitches = offsets + num_planes;
999
1000    width = stuff->width;
1001    height = stuff->height;
1002
1003    size = (*pPort->pAdaptor->ddQueryImageAttributes) (pPort, pImage,
1004                                                       &width, &height, offsets,
1005                                                       pitches);
1006
1007    rep = (xvQueryImageAttributesReply) {
1008        .type = X_Reply,
1009        .sequenceNumber = client->sequence,
1010        .length = planeLength = num_planes << 1,
1011        .num_planes = num_planes,
1012        .width = width,
1013        .height = height,
1014        .data_size = size
1015    };
1016
1017    _WriteQueryImageAttributesReply(client, &rep);
1018    if (client->swapped)
1019        SwapLongs((CARD32 *) offsets, planeLength);
1020    WriteToClient(client, planeLength << 2, offsets);
1021
1022    free(offsets);
1023
1024    return Success;
1025}
1026
1027static int
1028ProcXvListImageFormats(ClientPtr client)
1029{
1030    XvPortPtr pPort;
1031    XvImagePtr pImage;
1032    int i;
1033    xvListImageFormatsReply rep;
1034    xvImageFormatInfo info;
1035
1036    REQUEST(xvListImageFormatsReq);
1037
1038    REQUEST_SIZE_MATCH(xvListImageFormatsReq);
1039
1040    VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
1041
1042    rep = (xvListImageFormatsReply) {
1043        .type = X_Reply,
1044        .sequenceNumber = client->sequence,
1045        .num_formats = pPort->pAdaptor->nImages,
1046        .length =
1047            bytes_to_int32(pPort->pAdaptor->nImages * sz_xvImageFormatInfo)
1048    };
1049
1050    _WriteListImageFormatsReply(client, &rep);
1051
1052    pImage = pPort->pAdaptor->pImages;
1053
1054    for (i = 0; i < pPort->pAdaptor->nImages; i++, pImage++) {
1055        info.id = pImage->id;
1056        info.type = pImage->type;
1057        info.byte_order = pImage->byte_order;
1058        memcpy(&info.guid, pImage->guid, 16);
1059        info.bpp = pImage->bits_per_pixel;
1060        info.num_planes = pImage->num_planes;
1061        info.depth = pImage->depth;
1062        info.red_mask = pImage->red_mask;
1063        info.green_mask = pImage->green_mask;
1064        info.blue_mask = pImage->blue_mask;
1065        info.format = pImage->format;
1066        info.y_sample_bits = pImage->y_sample_bits;
1067        info.u_sample_bits = pImage->u_sample_bits;
1068        info.v_sample_bits = pImage->v_sample_bits;
1069        info.horz_y_period = pImage->horz_y_period;
1070        info.horz_u_period = pImage->horz_u_period;
1071        info.horz_v_period = pImage->horz_v_period;
1072        info.vert_y_period = pImage->vert_y_period;
1073        info.vert_u_period = pImage->vert_u_period;
1074        info.vert_v_period = pImage->vert_v_period;
1075        memcpy(&info.comp_order, pImage->component_order, 32);
1076        info.scanline_order = pImage->scanline_order;
1077        _WriteImageFormatInfo(client, &info);
1078    }
1079
1080    return Success;
1081}
1082
1083static int (*XvProcVector[xvNumRequests]) (ClientPtr) = {
1084ProcXvQueryExtension,
1085        ProcXvQueryAdaptors,
1086        ProcXvQueryEncodings,
1087        ProcXvGrabPort,
1088        ProcXvUngrabPort,
1089        ProcXvPutVideo,
1090        ProcXvPutStill,
1091        ProcXvGetVideo,
1092        ProcXvGetStill,
1093        ProcXvStopVideo,
1094        ProcXvSelectVideoNotify,
1095        ProcXvSelectPortNotify,
1096        ProcXvQueryBestSize,
1097        ProcXvSetPortAttribute,
1098        ProcXvGetPortAttribute,
1099        ProcXvQueryPortAttributes,
1100        ProcXvListImageFormats,
1101        ProcXvQueryImageAttributes, ProcXvPutImage, ProcXvShmPutImage,};
1102
1103int
1104ProcXvDispatch(ClientPtr client)
1105{
1106    REQUEST(xReq);
1107
1108    UpdateCurrentTime();
1109
1110    if (stuff->data >= xvNumRequests) {
1111        SendErrorToClient(client, XvReqCode, stuff->data, 0, BadRequest);
1112        return BadRequest;
1113    }
1114
1115    return XvProcVector[stuff->data] (client);
1116}
1117
1118/* Swapped Procs */
1119
1120static int
1121SProcXvQueryExtension(ClientPtr client)
1122{
1123    REQUEST(xvQueryExtensionReq);
1124    REQUEST_SIZE_MATCH(xvQueryExtensionReq);
1125    swaps(&stuff->length);
1126    return XvProcVector[xv_QueryExtension] (client);
1127}
1128
1129static int
1130SProcXvQueryAdaptors(ClientPtr client)
1131{
1132    REQUEST(xvQueryAdaptorsReq);
1133    REQUEST_SIZE_MATCH(xvQueryAdaptorsReq);
1134    swaps(&stuff->length);
1135    swapl(&stuff->window);
1136    return XvProcVector[xv_QueryAdaptors] (client);
1137}
1138
1139static int
1140SProcXvQueryEncodings(ClientPtr client)
1141{
1142    REQUEST(xvQueryEncodingsReq);
1143    REQUEST_SIZE_MATCH(xvQueryEncodingsReq);
1144    swaps(&stuff->length);
1145    swapl(&stuff->port);
1146    return XvProcVector[xv_QueryEncodings] (client);
1147}
1148
1149static int
1150SProcXvGrabPort(ClientPtr client)
1151{
1152    REQUEST(xvGrabPortReq);
1153    REQUEST_SIZE_MATCH(xvGrabPortReq);
1154    swaps(&stuff->length);
1155    swapl(&stuff->port);
1156    swapl(&stuff->time);
1157    return XvProcVector[xv_GrabPort] (client);
1158}
1159
1160static int
1161SProcXvUngrabPort(ClientPtr client)
1162{
1163    REQUEST(xvUngrabPortReq);
1164    REQUEST_SIZE_MATCH(xvUngrabPortReq);
1165    swaps(&stuff->length);
1166    swapl(&stuff->port);
1167    swapl(&stuff->time);
1168    return XvProcVector[xv_UngrabPort] (client);
1169}
1170
1171static int
1172SProcXvPutVideo(ClientPtr client)
1173{
1174    REQUEST(xvPutVideoReq);
1175    REQUEST_SIZE_MATCH(xvPutVideoReq);
1176    swaps(&stuff->length);
1177    swapl(&stuff->port);
1178    swapl(&stuff->drawable);
1179    swapl(&stuff->gc);
1180    swaps(&stuff->vid_x);
1181    swaps(&stuff->vid_y);
1182    swaps(&stuff->vid_w);
1183    swaps(&stuff->vid_h);
1184    swaps(&stuff->drw_x);
1185    swaps(&stuff->drw_y);
1186    swaps(&stuff->drw_w);
1187    swaps(&stuff->drw_h);
1188    return XvProcVector[xv_PutVideo] (client);
1189}
1190
1191static int
1192SProcXvPutStill(ClientPtr client)
1193{
1194    REQUEST(xvPutStillReq);
1195    REQUEST_SIZE_MATCH(xvPutStillReq);
1196    swaps(&stuff->length);
1197    swapl(&stuff->port);
1198    swapl(&stuff->drawable);
1199    swapl(&stuff->gc);
1200    swaps(&stuff->vid_x);
1201    swaps(&stuff->vid_y);
1202    swaps(&stuff->vid_w);
1203    swaps(&stuff->vid_h);
1204    swaps(&stuff->drw_x);
1205    swaps(&stuff->drw_y);
1206    swaps(&stuff->drw_w);
1207    swaps(&stuff->drw_h);
1208    return XvProcVector[xv_PutStill] (client);
1209}
1210
1211static int
1212SProcXvGetVideo(ClientPtr client)
1213{
1214    REQUEST(xvGetVideoReq);
1215    REQUEST_SIZE_MATCH(xvGetVideoReq);
1216    swaps(&stuff->length);
1217    swapl(&stuff->port);
1218    swapl(&stuff->drawable);
1219    swapl(&stuff->gc);
1220    swaps(&stuff->vid_x);
1221    swaps(&stuff->vid_y);
1222    swaps(&stuff->vid_w);
1223    swaps(&stuff->vid_h);
1224    swaps(&stuff->drw_x);
1225    swaps(&stuff->drw_y);
1226    swaps(&stuff->drw_w);
1227    swaps(&stuff->drw_h);
1228    return XvProcVector[xv_GetVideo] (client);
1229}
1230
1231static int
1232SProcXvGetStill(ClientPtr client)
1233{
1234    REQUEST(xvGetStillReq);
1235    REQUEST_SIZE_MATCH(xvGetStillReq);
1236    swaps(&stuff->length);
1237    swapl(&stuff->port);
1238    swapl(&stuff->drawable);
1239    swapl(&stuff->gc);
1240    swaps(&stuff->vid_x);
1241    swaps(&stuff->vid_y);
1242    swaps(&stuff->vid_w);
1243    swaps(&stuff->vid_h);
1244    swaps(&stuff->drw_x);
1245    swaps(&stuff->drw_y);
1246    swaps(&stuff->drw_w);
1247    swaps(&stuff->drw_h);
1248    return XvProcVector[xv_GetStill] (client);
1249}
1250
1251static int
1252SProcXvPutImage(ClientPtr client)
1253{
1254    REQUEST(xvPutImageReq);
1255    REQUEST_AT_LEAST_SIZE(xvPutImageReq);
1256    swaps(&stuff->length);
1257    swapl(&stuff->port);
1258    swapl(&stuff->drawable);
1259    swapl(&stuff->gc);
1260    swapl(&stuff->id);
1261    swaps(&stuff->src_x);
1262    swaps(&stuff->src_y);
1263    swaps(&stuff->src_w);
1264    swaps(&stuff->src_h);
1265    swaps(&stuff->drw_x);
1266    swaps(&stuff->drw_y);
1267    swaps(&stuff->drw_w);
1268    swaps(&stuff->drw_h);
1269    swaps(&stuff->width);
1270    swaps(&stuff->height);
1271    return XvProcVector[xv_PutImage] (client);
1272}
1273
1274#ifdef MITSHM
1275static int
1276SProcXvShmPutImage(ClientPtr client)
1277{
1278    REQUEST(xvShmPutImageReq);
1279    REQUEST_SIZE_MATCH(xvShmPutImageReq);
1280    swaps(&stuff->length);
1281    swapl(&stuff->port);
1282    swapl(&stuff->drawable);
1283    swapl(&stuff->gc);
1284    swapl(&stuff->shmseg);
1285    swapl(&stuff->id);
1286    swapl(&stuff->offset);
1287    swaps(&stuff->src_x);
1288    swaps(&stuff->src_y);
1289    swaps(&stuff->src_w);
1290    swaps(&stuff->src_h);
1291    swaps(&stuff->drw_x);
1292    swaps(&stuff->drw_y);
1293    swaps(&stuff->drw_w);
1294    swaps(&stuff->drw_h);
1295    swaps(&stuff->width);
1296    swaps(&stuff->height);
1297    return XvProcVector[xv_ShmPutImage] (client);
1298}
1299#else                           /* MITSHM */
1300#define SProcXvShmPutImage ProcXvShmPutImage
1301#endif
1302
1303static int
1304SProcXvSelectVideoNotify(ClientPtr client)
1305{
1306    REQUEST(xvSelectVideoNotifyReq);
1307    REQUEST_SIZE_MATCH(xvSelectVideoNotifyReq);
1308    swaps(&stuff->length);
1309    swapl(&stuff->drawable);
1310    return XvProcVector[xv_SelectVideoNotify] (client);
1311}
1312
1313static int
1314SProcXvSelectPortNotify(ClientPtr client)
1315{
1316    REQUEST(xvSelectPortNotifyReq);
1317    REQUEST_SIZE_MATCH(xvSelectPortNotifyReq);
1318    swaps(&stuff->length);
1319    swapl(&stuff->port);
1320    return XvProcVector[xv_SelectPortNotify] (client);
1321}
1322
1323static int
1324SProcXvStopVideo(ClientPtr client)
1325{
1326    REQUEST(xvStopVideoReq);
1327    REQUEST_SIZE_MATCH(xvStopVideoReq);
1328    swaps(&stuff->length);
1329    swapl(&stuff->port);
1330    swapl(&stuff->drawable);
1331    return XvProcVector[xv_StopVideo] (client);
1332}
1333
1334static int
1335SProcXvSetPortAttribute(ClientPtr client)
1336{
1337    REQUEST(xvSetPortAttributeReq);
1338    REQUEST_SIZE_MATCH(xvSetPortAttributeReq);
1339    swaps(&stuff->length);
1340    swapl(&stuff->port);
1341    swapl(&stuff->attribute);
1342    swapl(&stuff->value);
1343    return XvProcVector[xv_SetPortAttribute] (client);
1344}
1345
1346static int
1347SProcXvGetPortAttribute(ClientPtr client)
1348{
1349    REQUEST(xvGetPortAttributeReq);
1350    REQUEST_SIZE_MATCH(xvGetPortAttributeReq);
1351    swaps(&stuff->length);
1352    swapl(&stuff->port);
1353    swapl(&stuff->attribute);
1354    return XvProcVector[xv_GetPortAttribute] (client);
1355}
1356
1357static int
1358SProcXvQueryBestSize(ClientPtr client)
1359{
1360    REQUEST(xvQueryBestSizeReq);
1361    REQUEST_SIZE_MATCH(xvQueryBestSizeReq);
1362    swaps(&stuff->length);
1363    swapl(&stuff->port);
1364    swaps(&stuff->vid_w);
1365    swaps(&stuff->vid_h);
1366    swaps(&stuff->drw_w);
1367    swaps(&stuff->drw_h);
1368    return XvProcVector[xv_QueryBestSize] (client);
1369}
1370
1371static int
1372SProcXvQueryPortAttributes(ClientPtr client)
1373{
1374    REQUEST(xvQueryPortAttributesReq);
1375    REQUEST_SIZE_MATCH(xvQueryPortAttributesReq);
1376    swaps(&stuff->length);
1377    swapl(&stuff->port);
1378    return XvProcVector[xv_QueryPortAttributes] (client);
1379}
1380
1381static int
1382SProcXvQueryImageAttributes(ClientPtr client)
1383{
1384    REQUEST(xvQueryImageAttributesReq);
1385    REQUEST_SIZE_MATCH(xvQueryImageAttributesReq);
1386    swaps(&stuff->length);
1387    swapl(&stuff->port);
1388    swapl(&stuff->id);
1389    swaps(&stuff->width);
1390    swaps(&stuff->height);
1391    return XvProcVector[xv_QueryImageAttributes] (client);
1392}
1393
1394static int
1395SProcXvListImageFormats(ClientPtr client)
1396{
1397    REQUEST(xvListImageFormatsReq);
1398    REQUEST_SIZE_MATCH(xvListImageFormatsReq);
1399    swaps(&stuff->length);
1400    swapl(&stuff->port);
1401    return XvProcVector[xv_ListImageFormats] (client);
1402}
1403
1404static int (*SXvProcVector[xvNumRequests]) (ClientPtr) = {
1405SProcXvQueryExtension,
1406        SProcXvQueryAdaptors,
1407        SProcXvQueryEncodings,
1408        SProcXvGrabPort,
1409        SProcXvUngrabPort,
1410        SProcXvPutVideo,
1411        SProcXvPutStill,
1412        SProcXvGetVideo,
1413        SProcXvGetStill,
1414        SProcXvStopVideo,
1415        SProcXvSelectVideoNotify,
1416        SProcXvSelectPortNotify,
1417        SProcXvQueryBestSize,
1418        SProcXvSetPortAttribute,
1419        SProcXvGetPortAttribute,
1420        SProcXvQueryPortAttributes,
1421        SProcXvListImageFormats,
1422        SProcXvQueryImageAttributes, SProcXvPutImage, SProcXvShmPutImage,};
1423
1424int
1425SProcXvDispatch(ClientPtr client)
1426{
1427    REQUEST(xReq);
1428
1429    UpdateCurrentTime();
1430
1431    if (stuff->data >= xvNumRequests) {
1432        SendErrorToClient(client, XvReqCode, stuff->data, 0, BadRequest);
1433        return BadRequest;
1434    }
1435
1436    return SXvProcVector[stuff->data] (client);
1437}
1438
1439#ifdef PANORAMIX
1440static int
1441XineramaXvStopVideo(ClientPtr client)
1442{
1443    int result, i;
1444    PanoramiXRes *draw, *port;
1445
1446    REQUEST(xvStopVideoReq);
1447    REQUEST_SIZE_MATCH(xvStopVideoReq);
1448
1449    result = dixLookupResourceByClass((void **) &draw, stuff->drawable,
1450                                      XRC_DRAWABLE, client, DixWriteAccess);
1451    if (result != Success)
1452        return (result == BadValue) ? BadDrawable : result;
1453
1454    result = dixLookupResourceByType((void **) &port, stuff->port,
1455                                     XvXRTPort, client, DixReadAccess);
1456    if (result != Success)
1457        return result;
1458
1459    FOR_NSCREENS_BACKWARD(i) {
1460        if (port->info[i].id) {
1461            stuff->drawable = draw->info[i].id;
1462            stuff->port = port->info[i].id;
1463            result = ProcXvStopVideo(client);
1464        }
1465    }
1466
1467    return result;
1468}
1469
1470static int
1471XineramaXvSetPortAttribute(ClientPtr client)
1472{
1473    REQUEST(xvSetPortAttributeReq);
1474    PanoramiXRes *port;
1475    int result, i;
1476
1477    REQUEST_SIZE_MATCH(xvSetPortAttributeReq);
1478
1479    result = dixLookupResourceByType((void **) &port, stuff->port,
1480                                     XvXRTPort, client, DixReadAccess);
1481    if (result != Success)
1482        return result;
1483
1484    FOR_NSCREENS_BACKWARD(i) {
1485        if (port->info[i].id) {
1486            stuff->port = port->info[i].id;
1487            result = ProcXvSetPortAttribute(client);
1488        }
1489    }
1490    return result;
1491}
1492
1493#ifdef MITSHM
1494static int
1495XineramaXvShmPutImage(ClientPtr client)
1496{
1497    REQUEST(xvShmPutImageReq);
1498    PanoramiXRes *draw, *gc, *port;
1499    Bool send_event = stuff->send_event;
1500    Bool isRoot;
1501    int result, i, x, y;
1502
1503    REQUEST_SIZE_MATCH(xvShmPutImageReq);
1504
1505    result = dixLookupResourceByClass((void **) &draw, stuff->drawable,
1506                                      XRC_DRAWABLE, client, DixWriteAccess);
1507    if (result != Success)
1508        return (result == BadValue) ? BadDrawable : result;
1509
1510    result = dixLookupResourceByType((void **) &gc, stuff->gc,
1511                                     XRT_GC, client, DixReadAccess);
1512    if (result != Success)
1513        return result;
1514
1515    result = dixLookupResourceByType((void **) &port, stuff->port,
1516                                     XvXRTPort, client, DixReadAccess);
1517    if (result != Success)
1518        return result;
1519
1520    isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
1521
1522    x = stuff->drw_x;
1523    y = stuff->drw_y;
1524
1525    FOR_NSCREENS_BACKWARD(i) {
1526        if (port->info[i].id) {
1527            stuff->drawable = draw->info[i].id;
1528            stuff->port = port->info[i].id;
1529            stuff->gc = gc->info[i].id;
1530            stuff->drw_x = x;
1531            stuff->drw_y = y;
1532            if (isRoot) {
1533                stuff->drw_x -= screenInfo.screens[i]->x;
1534                stuff->drw_y -= screenInfo.screens[i]->y;
1535            }
1536            stuff->send_event = (send_event && !i) ? 1 : 0;
1537
1538            result = ProcXvShmPutImage(client);
1539        }
1540    }
1541    return result;
1542}
1543#else
1544#define XineramaXvShmPutImage ProcXvShmPutImage
1545#endif
1546
1547static int
1548XineramaXvPutImage(ClientPtr client)
1549{
1550    REQUEST(xvPutImageReq);
1551    PanoramiXRes *draw, *gc, *port;
1552    Bool isRoot;
1553    int result, i, x, y;
1554
1555    REQUEST_AT_LEAST_SIZE(xvPutImageReq);
1556
1557    result = dixLookupResourceByClass((void **) &draw, stuff->drawable,
1558                                      XRC_DRAWABLE, client, DixWriteAccess);
1559    if (result != Success)
1560        return (result == BadValue) ? BadDrawable : result;
1561
1562    result = dixLookupResourceByType((void **) &gc, stuff->gc,
1563                                     XRT_GC, client, DixReadAccess);
1564    if (result != Success)
1565        return result;
1566
1567    result = dixLookupResourceByType((void **) &port, stuff->port,
1568                                     XvXRTPort, client, DixReadAccess);
1569    if (result != Success)
1570        return result;
1571
1572    isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
1573
1574    x = stuff->drw_x;
1575    y = stuff->drw_y;
1576
1577    FOR_NSCREENS_BACKWARD(i) {
1578        if (port->info[i].id) {
1579            stuff->drawable = draw->info[i].id;
1580            stuff->port = port->info[i].id;
1581            stuff->gc = gc->info[i].id;
1582            stuff->drw_x = x;
1583            stuff->drw_y = y;
1584            if (isRoot) {
1585                stuff->drw_x -= screenInfo.screens[i]->x;
1586                stuff->drw_y -= screenInfo.screens[i]->y;
1587            }
1588
1589            result = ProcXvPutImage(client);
1590        }
1591    }
1592    return result;
1593}
1594
1595static int
1596XineramaXvPutVideo(ClientPtr client)
1597{
1598    REQUEST(xvPutImageReq);
1599    PanoramiXRes *draw, *gc, *port;
1600    Bool isRoot;
1601    int result, i, x, y;
1602
1603    REQUEST_AT_LEAST_SIZE(xvPutVideoReq);
1604
1605    result = dixLookupResourceByClass((void **) &draw, stuff->drawable,
1606                                      XRC_DRAWABLE, client, DixWriteAccess);
1607    if (result != Success)
1608        return (result == BadValue) ? BadDrawable : result;
1609
1610    result = dixLookupResourceByType((void **) &gc, stuff->gc,
1611                                     XRT_GC, client, DixReadAccess);
1612    if (result != Success)
1613        return result;
1614
1615    result = dixLookupResourceByType((void **) &port, stuff->port,
1616                                     XvXRTPort, client, DixReadAccess);
1617    if (result != Success)
1618        return result;
1619
1620    isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
1621
1622    x = stuff->drw_x;
1623    y = stuff->drw_y;
1624
1625    FOR_NSCREENS_BACKWARD(i) {
1626        if (port->info[i].id) {
1627            stuff->drawable = draw->info[i].id;
1628            stuff->port = port->info[i].id;
1629            stuff->gc = gc->info[i].id;
1630            stuff->drw_x = x;
1631            stuff->drw_y = y;
1632            if (isRoot) {
1633                stuff->drw_x -= screenInfo.screens[i]->x;
1634                stuff->drw_y -= screenInfo.screens[i]->y;
1635            }
1636
1637            result = ProcXvPutVideo(client);
1638        }
1639    }
1640    return result;
1641}
1642
1643static int
1644XineramaXvPutStill(ClientPtr client)
1645{
1646    REQUEST(xvPutImageReq);
1647    PanoramiXRes *draw, *gc, *port;
1648    Bool isRoot;
1649    int result, i, x, y;
1650
1651    REQUEST_AT_LEAST_SIZE(xvPutImageReq);
1652
1653    result = dixLookupResourceByClass((void **) &draw, stuff->drawable,
1654                                      XRC_DRAWABLE, client, DixWriteAccess);
1655    if (result != Success)
1656        return (result == BadValue) ? BadDrawable : result;
1657
1658    result = dixLookupResourceByType((void **) &gc, stuff->gc,
1659                                     XRT_GC, client, DixReadAccess);
1660    if (result != Success)
1661        return result;
1662
1663    result = dixLookupResourceByType((void **) &port, stuff->port,
1664                                     XvXRTPort, client, DixReadAccess);
1665    if (result != Success)
1666        return result;
1667
1668    isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
1669
1670    x = stuff->drw_x;
1671    y = stuff->drw_y;
1672
1673    FOR_NSCREENS_BACKWARD(i) {
1674        if (port->info[i].id) {
1675            stuff->drawable = draw->info[i].id;
1676            stuff->port = port->info[i].id;
1677            stuff->gc = gc->info[i].id;
1678            stuff->drw_x = x;
1679            stuff->drw_y = y;
1680            if (isRoot) {
1681                stuff->drw_x -= screenInfo.screens[i]->x;
1682                stuff->drw_y -= screenInfo.screens[i]->y;
1683            }
1684
1685            result = ProcXvPutStill(client);
1686        }
1687    }
1688    return result;
1689}
1690
1691static Bool
1692isImageAdaptor(XvAdaptorPtr pAdapt)
1693{
1694    return (pAdapt->type & XvImageMask) && (pAdapt->nImages > 0);
1695}
1696
1697static Bool
1698hasOverlay(XvAdaptorPtr pAdapt)
1699{
1700    int i;
1701
1702    for (i = 0; i < pAdapt->nAttributes; i++)
1703        if (!strcmp(pAdapt->pAttributes[i].name, "XV_COLORKEY"))
1704            return TRUE;
1705    return FALSE;
1706}
1707
1708static XvAdaptorPtr
1709matchAdaptor(ScreenPtr pScreen, XvAdaptorPtr refAdapt, Bool isOverlay)
1710{
1711    int i;
1712    XvScreenPtr xvsp =
1713        dixLookupPrivate(&pScreen->devPrivates, XvGetScreenKey());
1714    /* Do not try to go on if xv is not supported on this screen */
1715    if (xvsp == NULL)
1716        return NULL;
1717
1718    /* if the adaptor has the same name it's a perfect match */
1719    for (i = 0; i < xvsp->nAdaptors; i++) {
1720        XvAdaptorPtr pAdapt = xvsp->pAdaptors + i;
1721
1722        if (!strcmp(refAdapt->name, pAdapt->name))
1723            return pAdapt;
1724    }
1725
1726    /* otherwise we only look for XvImage adaptors */
1727    if (!isImageAdaptor(refAdapt))
1728        return NULL;
1729
1730    /* prefer overlay/overlay non-overlay/non-overlay pairing */
1731    for (i = 0; i < xvsp->nAdaptors; i++) {
1732        XvAdaptorPtr pAdapt = xvsp->pAdaptors + i;
1733
1734        if (isImageAdaptor(pAdapt) && isOverlay == hasOverlay(pAdapt))
1735            return pAdapt;
1736    }
1737
1738    /* but we'll take any XvImage pairing if we can get it */
1739    for (i = 0; i < xvsp->nAdaptors; i++) {
1740        XvAdaptorPtr pAdapt = xvsp->pAdaptors + i;
1741
1742        if (isImageAdaptor(pAdapt))
1743            return pAdapt;
1744    }
1745    return NULL;
1746}
1747
1748void
1749XineramifyXv(void)
1750{
1751    XvScreenPtr xvsp0 =
1752        dixLookupPrivate(&screenInfo.screens[0]->devPrivates, XvGetScreenKey());
1753    XvAdaptorPtr MatchingAdaptors[MAXSCREENS];
1754    int i, j, k;
1755
1756    XvXRTPort = CreateNewResourceType(XineramaDeleteResource, "XvXRTPort");
1757
1758    if (!xvsp0 || !XvXRTPort)
1759        return;
1760    SetResourceTypeErrorValue(XvXRTPort, _XvBadPort);
1761
1762    for (i = 0; i < xvsp0->nAdaptors; i++) {
1763        Bool isOverlay;
1764        XvAdaptorPtr refAdapt = xvsp0->pAdaptors + i;
1765
1766        if (!(refAdapt->type & XvInputMask))
1767            continue;
1768
1769        MatchingAdaptors[0] = refAdapt;
1770        isOverlay = hasOverlay(refAdapt);
1771        FOR_NSCREENS_FORWARD_SKIP(j)
1772            MatchingAdaptors[j] =
1773            matchAdaptor(screenInfo.screens[j], refAdapt, isOverlay);
1774
1775        /* now create a resource for each port */
1776        for (j = 0; j < refAdapt->nPorts; j++) {
1777            PanoramiXRes *port = malloc(sizeof(PanoramiXRes));
1778
1779            if (!port)
1780                break;
1781
1782            FOR_NSCREENS(k) {
1783                if (MatchingAdaptors[k] && (MatchingAdaptors[k]->nPorts > j))
1784                    port->info[k].id = MatchingAdaptors[k]->base_id + j;
1785                else
1786                    port->info[k].id = 0;
1787            }
1788            AddResource(port->info[0].id, XvXRTPort, port);
1789        }
1790    }
1791
1792    /* munge the dispatch vector */
1793    XvProcVector[xv_PutVideo] = XineramaXvPutVideo;
1794    XvProcVector[xv_PutStill] = XineramaXvPutStill;
1795    XvProcVector[xv_StopVideo] = XineramaXvStopVideo;
1796    XvProcVector[xv_SetPortAttribute] = XineramaXvSetPortAttribute;
1797    XvProcVector[xv_PutImage] = XineramaXvPutImage;
1798    XvProcVector[xv_ShmPutImage] = XineramaXvShmPutImage;
1799}
1800#endif                          /* PANORAMIX */
1801
1802void
1803XvResetProcVector(void)
1804{
1805#ifdef PANORAMIX
1806    XvProcVector[xv_PutVideo] = ProcXvPutVideo;
1807    XvProcVector[xv_PutStill] = ProcXvPutStill;
1808    XvProcVector[xv_StopVideo] = ProcXvStopVideo;
1809    XvProcVector[xv_SetPortAttribute] = ProcXvSetPortAttribute;
1810    XvProcVector[xv_PutImage] = ProcXvPutImage;
1811    XvProcVector[xv_ShmPutImage] = ProcXvShmPutImage;
1812#endif
1813}
1814