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