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