xvdisp.c revision 45bb0b75
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  swaps(&stuff->length, n);
1284  return XvProcVector[xv_QueryExtension](client);
1285}
1286
1287static int
1288SProcXvQueryAdaptors(ClientPtr client)
1289{
1290  char n;
1291  REQUEST(xvQueryAdaptorsReq);
1292  swaps(&stuff->length, n);
1293  swapl(&stuff->window, n);
1294  return XvProcVector[xv_QueryAdaptors](client);
1295}
1296
1297static int
1298SProcXvQueryEncodings(ClientPtr client)
1299{
1300  char n;
1301  REQUEST(xvQueryEncodingsReq);
1302  swaps(&stuff->length, n);
1303  swapl(&stuff->port, n);
1304  return XvProcVector[xv_QueryEncodings](client);
1305}
1306
1307static int
1308SProcXvGrabPort(ClientPtr client)
1309{
1310  char n;
1311  REQUEST(xvGrabPortReq);
1312  swaps(&stuff->length, n);
1313  swapl(&stuff->port, n);
1314  swapl(&stuff->time, n);
1315  return XvProcVector[xv_GrabPort](client);
1316}
1317
1318static int
1319SProcXvUngrabPort(ClientPtr client)
1320{
1321  char n;
1322  REQUEST(xvUngrabPortReq);
1323  swaps(&stuff->length, n);
1324  swapl(&stuff->port, n);
1325  swapl(&stuff->time, n);
1326  return XvProcVector[xv_UngrabPort](client);
1327}
1328
1329static int
1330SProcXvPutVideo(ClientPtr client)
1331{
1332  char n;
1333  REQUEST(xvPutVideoReq);
1334  swaps(&stuff->length, n);
1335  swapl(&stuff->port, n);
1336  swapl(&stuff->drawable, n);
1337  swapl(&stuff->gc, n);
1338  swaps(&stuff->vid_x, n);
1339  swaps(&stuff->vid_y, n);
1340  swaps(&stuff->vid_w, n);
1341  swaps(&stuff->vid_h, n);
1342  swaps(&stuff->drw_x, n);
1343  swaps(&stuff->drw_y, n);
1344  swaps(&stuff->drw_w, n);
1345  swaps(&stuff->drw_h, n);
1346  return XvProcVector[xv_PutVideo](client);
1347}
1348
1349static int
1350SProcXvPutStill(ClientPtr client)
1351{
1352  char n;
1353  REQUEST(xvPutStillReq);
1354  swaps(&stuff->length, n);
1355  swapl(&stuff->port, n);
1356  swapl(&stuff->drawable, n);
1357  swapl(&stuff->gc, n);
1358  swaps(&stuff->vid_x, n);
1359  swaps(&stuff->vid_y, n);
1360  swaps(&stuff->vid_w, n);
1361  swaps(&stuff->vid_h, n);
1362  swaps(&stuff->drw_x, n);
1363  swaps(&stuff->drw_y, n);
1364  swaps(&stuff->drw_w, n);
1365  swaps(&stuff->drw_h, n);
1366  return XvProcVector[xv_PutStill](client);
1367}
1368
1369static int
1370SProcXvGetVideo(ClientPtr client)
1371{
1372  char n;
1373  REQUEST(xvGetVideoReq);
1374  swaps(&stuff->length, n);
1375  swapl(&stuff->port, n);
1376  swapl(&stuff->drawable, n);
1377  swapl(&stuff->gc, n);
1378  swaps(&stuff->vid_x, n);
1379  swaps(&stuff->vid_y, n);
1380  swaps(&stuff->vid_w, n);
1381  swaps(&stuff->vid_h, n);
1382  swaps(&stuff->drw_x, n);
1383  swaps(&stuff->drw_y, n);
1384  swaps(&stuff->drw_w, n);
1385  swaps(&stuff->drw_h, n);
1386  return XvProcVector[xv_GetVideo](client);
1387}
1388
1389static int
1390SProcXvGetStill(ClientPtr client)
1391{
1392  char n;
1393  REQUEST(xvGetStillReq);
1394  swaps(&stuff->length, n);
1395  swapl(&stuff->port, n);
1396  swapl(&stuff->drawable, n);
1397  swapl(&stuff->gc, n);
1398  swaps(&stuff->vid_x, n);
1399  swaps(&stuff->vid_y, n);
1400  swaps(&stuff->vid_w, n);
1401  swaps(&stuff->vid_h, n);
1402  swaps(&stuff->drw_x, n);
1403  swaps(&stuff->drw_y, n);
1404  swaps(&stuff->drw_w, n);
1405  swaps(&stuff->drw_h, n);
1406  return XvProcVector[xv_GetStill](client);
1407}
1408
1409static int
1410SProcXvPutImage(ClientPtr client)
1411{
1412  char n;
1413  REQUEST(xvPutImageReq);
1414  swaps(&stuff->length, n);
1415  swapl(&stuff->port, n);
1416  swapl(&stuff->drawable, n);
1417  swapl(&stuff->gc, n);
1418  swapl(&stuff->id, n);
1419  swaps(&stuff->src_x, n);
1420  swaps(&stuff->src_y, n);
1421  swaps(&stuff->src_w, n);
1422  swaps(&stuff->src_h, n);
1423  swaps(&stuff->drw_x, n);
1424  swaps(&stuff->drw_y, n);
1425  swaps(&stuff->drw_w, n);
1426  swaps(&stuff->drw_h, n);
1427  swaps(&stuff->width, n);
1428  swaps(&stuff->height, n);
1429  return XvProcVector[xv_PutImage](client);
1430}
1431
1432#ifdef MITSHM
1433static int
1434SProcXvShmPutImage(ClientPtr client)
1435{
1436  char n;
1437  REQUEST(xvShmPutImageReq);
1438  swaps(&stuff->length, n);
1439  swapl(&stuff->port, n);
1440  swapl(&stuff->drawable, n);
1441  swapl(&stuff->gc, n);
1442  swapl(&stuff->shmseg, n);
1443  swapl(&stuff->id, n);
1444  swapl(&stuff->offset, n);
1445  swaps(&stuff->src_x, n);
1446  swaps(&stuff->src_y, n);
1447  swaps(&stuff->src_w, n);
1448  swaps(&stuff->src_h, n);
1449  swaps(&stuff->drw_x, n);
1450  swaps(&stuff->drw_y, n);
1451  swaps(&stuff->drw_w, n);
1452  swaps(&stuff->drw_h, n);
1453  swaps(&stuff->width, n);
1454  swaps(&stuff->height, n);
1455  return XvProcVector[xv_ShmPutImage](client);
1456}
1457#else /* MITSHM */
1458#define SProcXvShmPutImage ProcXvShmPutImage
1459#endif
1460
1461static int
1462SProcXvSelectVideoNotify(ClientPtr client)
1463{
1464  char n;
1465  REQUEST(xvSelectVideoNotifyReq);
1466  swaps(&stuff->length, n);
1467  swapl(&stuff->drawable, n);
1468  return XvProcVector[xv_SelectVideoNotify](client);
1469}
1470
1471static int
1472SProcXvSelectPortNotify(ClientPtr client)
1473{
1474  char n;
1475  REQUEST(xvSelectPortNotifyReq);
1476  swaps(&stuff->length, n);
1477  swapl(&stuff->port, n);
1478  return XvProcVector[xv_SelectPortNotify](client);
1479}
1480
1481static int
1482SProcXvStopVideo(ClientPtr client)
1483{
1484  char n;
1485  REQUEST(xvStopVideoReq);
1486  swaps(&stuff->length, n);
1487  swapl(&stuff->port, n);
1488  swapl(&stuff->drawable, n);
1489  return XvProcVector[xv_StopVideo](client);
1490}
1491
1492static int
1493SProcXvSetPortAttribute(ClientPtr client)
1494{
1495  char n;
1496  REQUEST(xvSetPortAttributeReq);
1497  swaps(&stuff->length, n);
1498  swapl(&stuff->port, n);
1499  swapl(&stuff->attribute, n);
1500  swapl(&stuff->value, n);
1501  return XvProcVector[xv_SetPortAttribute](client);
1502}
1503
1504static int
1505SProcXvGetPortAttribute(ClientPtr client)
1506{
1507  char n;
1508  REQUEST(xvGetPortAttributeReq);
1509  swaps(&stuff->length, n);
1510  swapl(&stuff->port, n);
1511  swapl(&stuff->attribute, n);
1512  return XvProcVector[xv_GetPortAttribute](client);
1513}
1514
1515static int
1516SProcXvQueryBestSize(ClientPtr client)
1517{
1518  char n;
1519  REQUEST(xvQueryBestSizeReq);
1520  swaps(&stuff->length, n);
1521  swapl(&stuff->port, n);
1522  swaps(&stuff->vid_w, n);
1523  swaps(&stuff->vid_h, n);
1524  swaps(&stuff->drw_w, n);
1525  swaps(&stuff->drw_h, n);
1526  return XvProcVector[xv_QueryBestSize](client);
1527}
1528
1529static int
1530SProcXvQueryPortAttributes(ClientPtr client)
1531{
1532  char n;
1533  REQUEST(xvQueryPortAttributesReq);
1534  swaps(&stuff->length, n);
1535  swapl(&stuff->port, n);
1536  return XvProcVector[xv_QueryPortAttributes](client);
1537}
1538
1539static int
1540SProcXvQueryImageAttributes(ClientPtr client)
1541{
1542  char n;
1543  REQUEST(xvQueryImageAttributesReq);
1544  swaps(&stuff->length, n);
1545  swapl(&stuff->port, n);
1546  swapl(&stuff->id, n);
1547  swaps(&stuff->width, n);
1548  swaps(&stuff->height, n);
1549  return XvProcVector[xv_QueryImageAttributes](client);
1550}
1551
1552static int
1553SProcXvListImageFormats(ClientPtr client)
1554{
1555  char n;
1556  REQUEST(xvListImageFormatsReq);
1557  swaps(&stuff->length, n);
1558  swapl(&stuff->port, n);
1559  return XvProcVector[xv_ListImageFormats](client);
1560}
1561
1562static int (*SXvProcVector[xvNumRequests])(ClientPtr) = {
1563    SProcXvQueryExtension,
1564    SProcXvQueryAdaptors,
1565    SProcXvQueryEncodings,
1566    SProcXvGrabPort,
1567    SProcXvUngrabPort,
1568    SProcXvPutVideo,
1569    SProcXvPutStill,
1570    SProcXvGetVideo,
1571    SProcXvGetStill,
1572    SProcXvStopVideo,
1573    SProcXvSelectVideoNotify,
1574    SProcXvSelectPortNotify,
1575    SProcXvQueryBestSize,
1576    SProcXvSetPortAttribute,
1577    SProcXvGetPortAttribute,
1578    SProcXvQueryPortAttributes,
1579    SProcXvListImageFormats,
1580    SProcXvQueryImageAttributes,
1581    SProcXvPutImage,
1582    SProcXvShmPutImage,
1583};
1584
1585int
1586SProcXvDispatch(ClientPtr client)
1587{
1588  REQUEST(xReq);
1589
1590  UpdateCurrentTime();
1591
1592  if (stuff->data >= xvNumRequests) {
1593    SendErrorToClient(client, XvReqCode, stuff->data, 0, BadRequest);
1594    return BadRequest;
1595  }
1596
1597  return SXvProcVector[stuff->data](client);
1598}
1599
1600#ifdef PANORAMIX
1601static int
1602XineramaXvStopVideo(ClientPtr client)
1603{
1604   int result, i;
1605   PanoramiXRes *draw, *port;
1606   REQUEST(xvStopVideoReq);
1607   REQUEST_SIZE_MATCH(xvStopVideoReq);
1608
1609   result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
1610				     XRC_DRAWABLE, client, DixWriteAccess);
1611   if (result != Success)
1612       return (result == BadValue) ? BadDrawable : result;
1613
1614   result = dixLookupResourceByType((pointer *)&port, stuff->port,
1615				    XvXRTPort, client, DixReadAccess);
1616   if (result != Success)
1617       return result;
1618
1619   FOR_NSCREENS_BACKWARD(i) {
1620	if(port->info[i].id) {
1621	   stuff->drawable = draw->info[i].id;
1622	   stuff->port = port->info[i].id;
1623	   result = ProcXvStopVideo(client);
1624     	}
1625   }
1626
1627   return result;
1628}
1629
1630static int
1631XineramaXvSetPortAttribute(ClientPtr client)
1632{
1633    REQUEST(xvSetPortAttributeReq);
1634    PanoramiXRes *port;
1635    int result, i;
1636
1637    REQUEST_SIZE_MATCH(xvSetPortAttributeReq);
1638
1639    result = dixLookupResourceByType((pointer *)&port, stuff->port,
1640				     XvXRTPort, client, DixReadAccess);
1641    if (result != Success)
1642	return result;
1643
1644    FOR_NSCREENS_BACKWARD(i) {
1645	if(port->info[i].id) {
1646	   stuff->port = port->info[i].id;
1647	   result = ProcXvSetPortAttribute(client);
1648	}
1649    }
1650    return result;
1651}
1652
1653#ifdef MITSHM
1654static int
1655XineramaXvShmPutImage(ClientPtr client)
1656{
1657    REQUEST(xvShmPutImageReq);
1658    PanoramiXRes *draw, *gc, *port;
1659    Bool send_event = stuff->send_event;
1660    Bool isRoot;
1661    int result, i, x, y;
1662
1663    REQUEST_SIZE_MATCH(xvShmPutImageReq);
1664
1665    result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
1666				      XRC_DRAWABLE, client, DixWriteAccess);
1667    if (result != Success)
1668	return (result == BadValue) ? BadDrawable : result;
1669
1670    result = dixLookupResourceByType((pointer *)&gc, stuff->gc,
1671				     XRT_GC, client, DixReadAccess);
1672    if (result != Success)
1673        return result;
1674
1675    result = dixLookupResourceByType((pointer *)&port, stuff->port,
1676				     XvXRTPort, client, DixReadAccess);
1677    if (result != Success)
1678	return result;
1679
1680    isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
1681
1682    x = stuff->drw_x;
1683    y = stuff->drw_y;
1684
1685    FOR_NSCREENS_BACKWARD(i) {
1686	if(port->info[i].id) {
1687	   stuff->drawable = draw->info[i].id;
1688	   stuff->port = port->info[i].id;
1689	   stuff->gc = gc->info[i].id;
1690	   stuff->drw_x = x;
1691	   stuff->drw_y = y;
1692	   if(isRoot) {
1693		stuff->drw_x -= screenInfo.screens[i]->x;
1694		stuff->drw_y -= screenInfo.screens[i]->y;
1695	   }
1696	   stuff->send_event = (send_event && !i) ? 1 : 0;
1697
1698	   result = ProcXvShmPutImage(client);
1699	}
1700    }
1701    return result;
1702}
1703#else
1704#define XineramaXvShmPutImage ProcXvShmPutImage
1705#endif
1706
1707static int
1708XineramaXvPutImage(ClientPtr client)
1709{
1710    REQUEST(xvPutImageReq);
1711    PanoramiXRes *draw, *gc, *port;
1712    Bool isRoot;
1713    int result, i, x, y;
1714
1715    REQUEST_AT_LEAST_SIZE(xvPutImageReq);
1716
1717    result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
1718				      XRC_DRAWABLE, client, DixWriteAccess);
1719    if (result != Success)
1720	return (result == BadValue) ? BadDrawable : result;
1721
1722    result = dixLookupResourceByType((pointer *)&gc, stuff->gc,
1723				     XRT_GC, client, DixReadAccess);
1724    if (result != Success)
1725        return result;
1726
1727    result = dixLookupResourceByType((pointer *)&port, stuff->port,
1728				     XvXRTPort, client, DixReadAccess);
1729    if (result != Success)
1730	return result;
1731
1732    isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
1733
1734    x = stuff->drw_x;
1735    y = stuff->drw_y;
1736
1737    FOR_NSCREENS_BACKWARD(i) {
1738	if(port->info[i].id) {
1739	   stuff->drawable = draw->info[i].id;
1740	   stuff->port = port->info[i].id;
1741	   stuff->gc = gc->info[i].id;
1742	   stuff->drw_x = x;
1743	   stuff->drw_y = y;
1744	   if(isRoot) {
1745		stuff->drw_x -= screenInfo.screens[i]->x;
1746		stuff->drw_y -= screenInfo.screens[i]->y;
1747	   }
1748
1749	   result = ProcXvPutImage(client);
1750	}
1751    }
1752    return result;
1753}
1754
1755static int
1756XineramaXvPutVideo(ClientPtr client)
1757{
1758    REQUEST(xvPutImageReq);
1759    PanoramiXRes *draw, *gc, *port;
1760    Bool isRoot;
1761    int result, i, x, y;
1762
1763    REQUEST_AT_LEAST_SIZE(xvPutVideoReq);
1764
1765    result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
1766				      XRC_DRAWABLE, client, DixWriteAccess);
1767    if (result != Success)
1768	return (result == BadValue) ? BadDrawable : result;
1769
1770    result = dixLookupResourceByType((pointer *)&gc, stuff->gc,
1771				     XRT_GC, client, DixReadAccess);
1772    if (result != Success)
1773        return result;
1774
1775    result = dixLookupResourceByType((pointer *)&port, stuff->port,
1776				     XvXRTPort, client, DixReadAccess);
1777    if (result != Success)
1778	return result;
1779
1780    isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
1781
1782    x = stuff->drw_x;
1783    y = stuff->drw_y;
1784
1785    FOR_NSCREENS_BACKWARD(i) {
1786        if(port->info[i].id) {
1787           stuff->drawable = draw->info[i].id;
1788           stuff->port = port->info[i].id;
1789           stuff->gc = gc->info[i].id;
1790           stuff->drw_x = x;
1791           stuff->drw_y = y;
1792           if(isRoot) {
1793                stuff->drw_x -= screenInfo.screens[i]->x;
1794                stuff->drw_y -= screenInfo.screens[i]->y;
1795           }
1796
1797           result = ProcXvPutVideo(client);
1798        }
1799    }
1800    return result;
1801}
1802
1803static int
1804XineramaXvPutStill(ClientPtr client)
1805{
1806    REQUEST(xvPutImageReq);
1807    PanoramiXRes *draw, *gc, *port;
1808    Bool isRoot;
1809    int result, i, x, y;
1810
1811    REQUEST_AT_LEAST_SIZE(xvPutImageReq);
1812
1813    result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
1814				      XRC_DRAWABLE, client, DixWriteAccess);
1815    if (result != Success)
1816	return (result == BadValue) ? BadDrawable : result;
1817
1818    result = dixLookupResourceByType((pointer *)&gc, stuff->gc,
1819				     XRT_GC, client, DixReadAccess);
1820    if (result != Success)
1821        return result;
1822
1823    result = dixLookupResourceByType((pointer *)&port, stuff->port,
1824				     XvXRTPort, client, DixReadAccess);
1825    if (result != Success)
1826	return result;
1827
1828    isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
1829
1830    x = stuff->drw_x;
1831    y = stuff->drw_y;
1832
1833    FOR_NSCREENS_BACKWARD(i) {
1834        if(port->info[i].id) {
1835           stuff->drawable = draw->info[i].id;
1836           stuff->port = port->info[i].id;
1837           stuff->gc = gc->info[i].id;
1838           stuff->drw_x = x;
1839           stuff->drw_y = y;
1840           if(isRoot) {
1841                stuff->drw_x -= screenInfo.screens[i]->x;
1842                stuff->drw_y -= screenInfo.screens[i]->y;
1843           }
1844
1845           result = ProcXvPutStill(client);
1846        }
1847    }
1848    return result;
1849}
1850
1851static Bool
1852isImageAdaptor(XvAdaptorPtr pAdapt)
1853{
1854    return (pAdapt->type & XvImageMask) && (pAdapt->nImages > 0);
1855}
1856
1857static Bool
1858hasOverlay(XvAdaptorPtr pAdapt)
1859{
1860    int i;
1861    for(i = 0; i < pAdapt->nAttributes; i++)
1862	if(!strcmp(pAdapt->pAttributes[i].name, "XV_COLORKEY"))
1863	    return TRUE;
1864    return FALSE;
1865}
1866
1867static XvAdaptorPtr
1868matchAdaptor(ScreenPtr pScreen, XvAdaptorPtr refAdapt, Bool isOverlay)
1869{
1870    int i;
1871    XvScreenPtr xvsp = dixLookupPrivate(&pScreen->devPrivates, XvGetScreenKey());
1872    /* Do not try to go on if xv is not supported on this screen */
1873    if(xvsp == NULL)
1874	return NULL;
1875
1876    /* if the adaptor has the same name it's a perfect match */
1877    for(i = 0; i < xvsp->nAdaptors; i++) {
1878	XvAdaptorPtr pAdapt = xvsp->pAdaptors + i;
1879	if(!strcmp(refAdapt->name, pAdapt->name))
1880	    return pAdapt;
1881    }
1882
1883    /* otherwise we only look for XvImage adaptors */
1884    if(!isImageAdaptor(refAdapt))
1885	return NULL;
1886
1887    /* prefer overlay/overlay non-overlay/non-overlay pairing */
1888    for(i = 0; i < xvsp->nAdaptors; i++) {
1889	XvAdaptorPtr pAdapt = xvsp->pAdaptors + i;
1890	if(isImageAdaptor(pAdapt) && isOverlay == hasOverlay(pAdapt))
1891	    return pAdapt;
1892    }
1893
1894    /* but we'll take any XvImage pairing if we can get it */
1895    for(i = 0; i < xvsp->nAdaptors; i++) {
1896	XvAdaptorPtr pAdapt = xvsp->pAdaptors + i;
1897	if(isImageAdaptor(pAdapt))
1898	    return pAdapt;
1899    }
1900    return NULL;
1901}
1902
1903void XineramifyXv(void)
1904{
1905   XvScreenPtr xvsp0 = dixLookupPrivate(&screenInfo.screens[0]->devPrivates, XvGetScreenKey());
1906   XvAdaptorPtr MatchingAdaptors[MAXSCREENS];
1907   int i, j, k;
1908
1909   XvXRTPort = CreateNewResourceType(XineramaDeleteResource, "XvXRTPort");
1910
1911   if (!xvsp0 || !XvXRTPort) return;
1912   SetResourceTypeErrorValue(XvXRTPort, _XvBadPort);
1913
1914   for(i = 0; i < xvsp0->nAdaptors; i++) {
1915      Bool isOverlay;
1916      XvAdaptorPtr refAdapt = xvsp0->pAdaptors + i;
1917      if(!(refAdapt->type & XvInputMask)) continue;
1918
1919      MatchingAdaptors[0] = refAdapt;
1920      isOverlay = hasOverlay(refAdapt);
1921      for(j = 1; j < PanoramiXNumScreens; j++)
1922	 MatchingAdaptors[j] = matchAdaptor(screenInfo.screens[j], refAdapt, isOverlay);
1923
1924      /* now create a resource for each port */
1925      for(j = 0; j < refAdapt->nPorts; j++) {
1926	 PanoramiXRes *port = malloc(sizeof(PanoramiXRes));
1927	 if(!port)
1928	    break;
1929
1930	 for(k = 0; k < PanoramiXNumScreens; k++) {
1931	    if(MatchingAdaptors[k] && (MatchingAdaptors[k]->nPorts > j))
1932		port->info[k].id = MatchingAdaptors[k]->base_id + j;
1933	    else
1934		port->info[k].id = 0;
1935	 }
1936	 AddResource(port->info[0].id, XvXRTPort, port);
1937      }
1938   }
1939
1940   /* munge the dispatch vector */
1941   XvProcVector[xv_PutVideo]		= XineramaXvPutVideo;
1942   XvProcVector[xv_PutStill]		= XineramaXvPutStill;
1943   XvProcVector[xv_StopVideo]		= XineramaXvStopVideo;
1944   XvProcVector[xv_SetPortAttribute]	= XineramaXvSetPortAttribute;
1945   XvProcVector[xv_PutImage]		= XineramaXvPutImage;
1946   XvProcVector[xv_ShmPutImage]		= XineramaXvShmPutImage;
1947}
1948#endif /* PANORAMIX */
1949
1950void
1951XvResetProcVector(void)
1952{
1953#ifdef PANORAMIX
1954   XvProcVector[xv_PutVideo]		= ProcXvPutVideo;
1955   XvProcVector[xv_PutStill]		= ProcXvPutStill;
1956   XvProcVector[xv_StopVideo]		= ProcXvStopVideo;
1957   XvProcVector[xv_SetPortAttribute]	= ProcXvSetPortAttribute;
1958   XvProcVector[xv_PutImage]		= ProcXvPutImage;
1959   XvProcVector[xv_ShmPutImage]		= ProcXvShmPutImage;
1960#endif
1961}
1962