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