xvdisp.c revision 48a68b89
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;
1680    Bool isRoot;
1681    int result, i, x, y;
1682
1683    REQUEST_SIZE_MATCH(xvShmPutImageReq);
1684
1685    send_event = stuff->send_event;
1686
1687    result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
1688				      XRC_DRAWABLE, client, DixWriteAccess);
1689    if (result != Success)
1690	return (result == BadValue) ? BadDrawable : result;
1691
1692    result = dixLookupResourceByType((pointer *)&gc, stuff->gc,
1693				     XRT_GC, client, DixReadAccess);
1694    if (result != Success)
1695        return result;
1696
1697    result = dixLookupResourceByType((pointer *)&port, stuff->port,
1698				     XvXRTPort, client, DixReadAccess);
1699    if (result != Success)
1700	return result;
1701
1702    isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
1703
1704    x = stuff->drw_x;
1705    y = stuff->drw_y;
1706
1707    FOR_NSCREENS_BACKWARD(i) {
1708	if(port->info[i].id) {
1709	   stuff->drawable = draw->info[i].id;
1710	   stuff->port = port->info[i].id;
1711	   stuff->gc = gc->info[i].id;
1712	   stuff->drw_x = x;
1713	   stuff->drw_y = y;
1714	   if(isRoot) {
1715		stuff->drw_x -= screenInfo.screens[i]->x;
1716		stuff->drw_y -= screenInfo.screens[i]->y;
1717	   }
1718	   stuff->send_event = (send_event && !i) ? 1 : 0;
1719
1720	   result = ProcXvShmPutImage(client);
1721	}
1722    }
1723    return result;
1724}
1725#else
1726#define XineramaXvShmPutImage ProcXvShmPutImage
1727#endif
1728
1729static int
1730XineramaXvPutImage(ClientPtr client)
1731{
1732    REQUEST(xvPutImageReq);
1733    PanoramiXRes *draw, *gc, *port;
1734    Bool isRoot;
1735    int result, i, x, y;
1736
1737    REQUEST_AT_LEAST_SIZE(xvPutImageReq);
1738
1739    result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
1740				      XRC_DRAWABLE, client, DixWriteAccess);
1741    if (result != Success)
1742	return (result == BadValue) ? BadDrawable : result;
1743
1744    result = dixLookupResourceByType((pointer *)&gc, stuff->gc,
1745				     XRT_GC, client, DixReadAccess);
1746    if (result != Success)
1747        return result;
1748
1749    result = dixLookupResourceByType((pointer *)&port, stuff->port,
1750				     XvXRTPort, client, DixReadAccess);
1751    if (result != Success)
1752	return result;
1753
1754    isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
1755
1756    x = stuff->drw_x;
1757    y = stuff->drw_y;
1758
1759    FOR_NSCREENS_BACKWARD(i) {
1760	if(port->info[i].id) {
1761	   stuff->drawable = draw->info[i].id;
1762	   stuff->port = port->info[i].id;
1763	   stuff->gc = gc->info[i].id;
1764	   stuff->drw_x = x;
1765	   stuff->drw_y = y;
1766	   if(isRoot) {
1767		stuff->drw_x -= screenInfo.screens[i]->x;
1768		stuff->drw_y -= screenInfo.screens[i]->y;
1769	   }
1770
1771	   result = ProcXvPutImage(client);
1772	}
1773    }
1774    return result;
1775}
1776
1777static int
1778XineramaXvPutVideo(ClientPtr client)
1779{
1780    REQUEST(xvPutImageReq);
1781    PanoramiXRes *draw, *gc, *port;
1782    Bool isRoot;
1783    int result, i, x, y;
1784
1785    REQUEST_AT_LEAST_SIZE(xvPutVideoReq);
1786
1787    result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
1788				      XRC_DRAWABLE, client, DixWriteAccess);
1789    if (result != Success)
1790	return (result == BadValue) ? BadDrawable : result;
1791
1792    result = dixLookupResourceByType((pointer *)&gc, stuff->gc,
1793				     XRT_GC, client, DixReadAccess);
1794    if (result != Success)
1795        return result;
1796
1797    result = dixLookupResourceByType((pointer *)&port, stuff->port,
1798				     XvXRTPort, client, DixReadAccess);
1799    if (result != Success)
1800	return result;
1801
1802    isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
1803
1804    x = stuff->drw_x;
1805    y = stuff->drw_y;
1806
1807    FOR_NSCREENS_BACKWARD(i) {
1808        if(port->info[i].id) {
1809           stuff->drawable = draw->info[i].id;
1810           stuff->port = port->info[i].id;
1811           stuff->gc = gc->info[i].id;
1812           stuff->drw_x = x;
1813           stuff->drw_y = y;
1814           if(isRoot) {
1815                stuff->drw_x -= screenInfo.screens[i]->x;
1816                stuff->drw_y -= screenInfo.screens[i]->y;
1817           }
1818
1819           result = ProcXvPutVideo(client);
1820        }
1821    }
1822    return result;
1823}
1824
1825static int
1826XineramaXvPutStill(ClientPtr client)
1827{
1828    REQUEST(xvPutImageReq);
1829    PanoramiXRes *draw, *gc, *port;
1830    Bool isRoot;
1831    int result, i, x, y;
1832
1833    REQUEST_AT_LEAST_SIZE(xvPutImageReq);
1834
1835    result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
1836				      XRC_DRAWABLE, client, DixWriteAccess);
1837    if (result != Success)
1838	return (result == BadValue) ? BadDrawable : result;
1839
1840    result = dixLookupResourceByType((pointer *)&gc, stuff->gc,
1841				     XRT_GC, client, DixReadAccess);
1842    if (result != Success)
1843        return result;
1844
1845    result = dixLookupResourceByType((pointer *)&port, stuff->port,
1846				     XvXRTPort, client, DixReadAccess);
1847    if (result != Success)
1848	return result;
1849
1850    isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
1851
1852    x = stuff->drw_x;
1853    y = stuff->drw_y;
1854
1855    FOR_NSCREENS_BACKWARD(i) {
1856        if(port->info[i].id) {
1857           stuff->drawable = draw->info[i].id;
1858           stuff->port = port->info[i].id;
1859           stuff->gc = gc->info[i].id;
1860           stuff->drw_x = x;
1861           stuff->drw_y = y;
1862           if(isRoot) {
1863                stuff->drw_x -= screenInfo.screens[i]->x;
1864                stuff->drw_y -= screenInfo.screens[i]->y;
1865           }
1866
1867           result = ProcXvPutStill(client);
1868        }
1869    }
1870    return result;
1871}
1872
1873static Bool
1874isImageAdaptor(XvAdaptorPtr pAdapt)
1875{
1876    return (pAdapt->type & XvImageMask) && (pAdapt->nImages > 0);
1877}
1878
1879static Bool
1880hasOverlay(XvAdaptorPtr pAdapt)
1881{
1882    int i;
1883    for(i = 0; i < pAdapt->nAttributes; i++)
1884	if(!strcmp(pAdapt->pAttributes[i].name, "XV_COLORKEY"))
1885	    return TRUE;
1886    return FALSE;
1887}
1888
1889static XvAdaptorPtr
1890matchAdaptor(ScreenPtr pScreen, XvAdaptorPtr refAdapt, Bool isOverlay)
1891{
1892    int i;
1893    XvScreenPtr xvsp = dixLookupPrivate(&pScreen->devPrivates, XvGetScreenKey());
1894    /* Do not try to go on if xv is not supported on this screen */
1895    if(xvsp == NULL)
1896	return NULL;
1897
1898    /* if the adaptor has the same name it's a perfect match */
1899    for(i = 0; i < xvsp->nAdaptors; i++) {
1900	XvAdaptorPtr pAdapt = xvsp->pAdaptors + i;
1901	if(!strcmp(refAdapt->name, pAdapt->name))
1902	    return pAdapt;
1903    }
1904
1905    /* otherwise we only look for XvImage adaptors */
1906    if(!isImageAdaptor(refAdapt))
1907	return NULL;
1908
1909    /* prefer overlay/overlay non-overlay/non-overlay pairing */
1910    for(i = 0; i < xvsp->nAdaptors; i++) {
1911	XvAdaptorPtr pAdapt = xvsp->pAdaptors + i;
1912	if(isImageAdaptor(pAdapt) && isOverlay == hasOverlay(pAdapt))
1913	    return pAdapt;
1914    }
1915
1916    /* but we'll take any XvImage pairing if we can get it */
1917    for(i = 0; i < xvsp->nAdaptors; i++) {
1918	XvAdaptorPtr pAdapt = xvsp->pAdaptors + i;
1919	if(isImageAdaptor(pAdapt))
1920	    return pAdapt;
1921    }
1922    return NULL;
1923}
1924
1925void XineramifyXv(void)
1926{
1927   XvScreenPtr xvsp0 = dixLookupPrivate(&screenInfo.screens[0]->devPrivates, XvGetScreenKey());
1928   XvAdaptorPtr MatchingAdaptors[MAXSCREENS];
1929   int i, j, k;
1930
1931   XvXRTPort = CreateNewResourceType(XineramaDeleteResource, "XvXRTPort");
1932
1933   if (!xvsp0 || !XvXRTPort) return;
1934   SetResourceTypeErrorValue(XvXRTPort, _XvBadPort);
1935
1936   for(i = 0; i < xvsp0->nAdaptors; i++) {
1937      Bool isOverlay;
1938      XvAdaptorPtr refAdapt = xvsp0->pAdaptors + i;
1939      if(!(refAdapt->type & XvInputMask)) continue;
1940
1941      MatchingAdaptors[0] = refAdapt;
1942      isOverlay = hasOverlay(refAdapt);
1943      for(j = 1; j < PanoramiXNumScreens; j++)
1944	 MatchingAdaptors[j] = matchAdaptor(screenInfo.screens[j], refAdapt, isOverlay);
1945
1946      /* now create a resource for each port */
1947      for(j = 0; j < refAdapt->nPorts; j++) {
1948	 PanoramiXRes *port = malloc(sizeof(PanoramiXRes));
1949	 if(!port)
1950	    break;
1951
1952	 for(k = 0; k < PanoramiXNumScreens; k++) {
1953	    if(MatchingAdaptors[k] && (MatchingAdaptors[k]->nPorts > j))
1954		port->info[k].id = MatchingAdaptors[k]->base_id + j;
1955	    else
1956		port->info[k].id = 0;
1957	 }
1958	 AddResource(port->info[0].id, XvXRTPort, port);
1959      }
1960   }
1961
1962   /* munge the dispatch vector */
1963   XvProcVector[xv_PutVideo]		= XineramaXvPutVideo;
1964   XvProcVector[xv_PutStill]		= XineramaXvPutStill;
1965   XvProcVector[xv_StopVideo]		= XineramaXvStopVideo;
1966   XvProcVector[xv_SetPortAttribute]	= XineramaXvSetPortAttribute;
1967   XvProcVector[xv_PutImage]		= XineramaXvPutImage;
1968   XvProcVector[xv_ShmPutImage]		= XineramaXvShmPutImage;
1969}
1970#endif /* PANORAMIX */
1971
1972void
1973XvResetProcVector(void)
1974{
1975#ifdef PANORAMIX
1976   XvProcVector[xv_PutVideo]		= ProcXvPutVideo;
1977   XvProcVector[xv_PutStill]		= ProcXvPutStill;
1978   XvProcVector[xv_StopVideo]		= ProcXvStopVideo;
1979   XvProcVector[xv_SetPortAttribute]	= ProcXvSetPortAttribute;
1980   XvProcVector[xv_PutImage]		= ProcXvPutImage;
1981   XvProcVector[xv_ShmPutImage]		= ProcXvShmPutImage;
1982#endif
1983}
1984