Xv.c revision cdbfa18a
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/*
25** File:
26**
27**   Xv.c --- Xv library extension module.
28**
29** Author:
30**
31**   David Carver (Digital Workstation Engineering/Project Athena)
32**
33** Revisions:
34**
35**   26.06.91 Carver
36**     - changed XvFreeAdaptors to XvFreeAdaptorInfo
37**     - changed XvFreeEncodings to XvFreeEncodingInfo
38**
39**   11.06.91 Carver
40**     - changed SetPortControl to SetPortAttribute
41**     - changed GetPortControl to GetPortAttribute
42**     - changed QueryBestSize
43**
44**   15.05.91 Carver
45**     - version 2.0 upgrade
46**
47**   240.01.91 Carver
48**     - version 1.4 upgrade
49**
50*/
51
52#ifdef HAVE_CONFIG_H
53# include "config.h"
54#endif
55
56#include <stdio.h>
57#include "Xvlibint.h"
58#include <X11/extensions/Xext.h>
59#include <X11/extensions/extutil.h>
60#include <X11/extensions/XShm.h>
61#include <limits.h>
62
63#ifndef HAVE__XEATDATAWORDS
64static inline void _XEatDataWords(Display *dpy, unsigned long n)
65{
66# ifndef LONG64
67    if (n >= (ULONG_MAX >> 2))
68        _XIOError(dpy);
69# endif
70    _XEatData (dpy, n << 2);
71}
72#endif
73
74static XExtensionInfo _xv_info_data;
75static XExtensionInfo *xv_info = &_xv_info_data;
76static const char *xv_extension_name = XvName;
77
78#define XvCheckExtension(dpy, i, val) \
79  XextCheckExtension(dpy, i, xv_extension_name, val)
80
81static char *xv_error_string(Display *dpy, int code, XExtCodes *codes,
82			     char * buf, int n);
83static int xv_close_display(Display *dpy, XExtCodes *codes);
84static Bool xv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire);
85
86static XExtensionHooks xv_extension_hooks = {
87    NULL,                               /* create_gc */
88    NULL,                               /* copy_gc */
89    NULL,                               /* flush_gc */
90    NULL,                               /* free_gc */
91    NULL,                               /* create_font */
92    NULL,                               /* free_font */
93    xv_close_display,                   /* close_display */
94    xv_wire_to_event,                   /* wire_to_event */
95    NULL,                               /* event_to_wire */
96    NULL,                               /* error */
97    xv_error_string                     /* error_string */
98};
99
100
101static const char *xv_error_list[] =
102{
103   "BadPort",	    /* XvBadPort     */
104   "BadEncoding",   /* XvBadEncoding */
105   "BadControl"     /* XvBadControl  */
106};
107
108static XEXT_GENERATE_CLOSE_DISPLAY (xv_close_display, xv_info)
109
110
111static XEXT_GENERATE_FIND_DISPLAY (xv_find_display, xv_info,
112                                   xv_extension_name,
113                                   &xv_extension_hooks,
114				   XvNumEvents, NULL)
115
116
117static XEXT_GENERATE_ERROR_STRING (xv_error_string, xv_extension_name,
118                                   XvNumErrors, xv_error_list)
119
120
121int
122XvQueryExtension(
123     Display *dpy,
124     unsigned int *p_version,
125     unsigned int *p_revision,
126     unsigned int *p_requestBase,
127     unsigned int *p_eventBase,
128     unsigned int *p_errorBase
129){
130  XExtDisplayInfo *info = xv_find_display(dpy);
131  xvQueryExtensionReq *req;
132  xvQueryExtensionReply rep;
133
134  XvCheckExtension(dpy, info, XvBadExtension);
135
136  LockDisplay(dpy);
137
138  XvGetReq(QueryExtension, req);
139
140  if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
141     UnlockDisplay(dpy);
142     SyncHandle();
143     return XvBadExtension;
144  }
145
146  *p_version = rep.version;
147  *p_revision = rep.revision;
148  *p_requestBase = info->codes->major_opcode;
149  *p_eventBase = info->codes->first_event;
150  *p_errorBase = info->codes->first_error;
151
152  UnlockDisplay(dpy);
153  SyncHandle();
154
155  return Success;
156}
157
158int
159XvQueryAdaptors(
160     Display *dpy,
161     Window window,
162     unsigned int *p_nAdaptors,
163     XvAdaptorInfo **p_pAdaptors
164){
165  XExtDisplayInfo *info = xv_find_display(dpy);
166  xvQueryAdaptorsReq *req;
167  xvQueryAdaptorsReply rep;
168  int size,ii,jj;
169  char *name;
170  XvAdaptorInfo *pas, *pa;
171  XvFormat *pfs, *pf;
172  char *buffer;
173  union
174    {
175      char *buffer;
176      char *string;
177      xvAdaptorInfo *pa;
178      xvFormat *pf;
179    } u;
180
181  XvCheckExtension(dpy, info, XvBadExtension);
182
183  LockDisplay(dpy);
184
185  XvGetReq(QueryAdaptors, req);
186  req->window = window;
187
188  /* READ THE REPLY */
189
190  if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) {
191      UnlockDisplay(dpy);
192      SyncHandle();
193      return(XvBadReply);
194  }
195
196  size = rep.length << 2;
197  if ( (buffer = (char *)Xmalloc ((unsigned) size)) == NULL) {
198      UnlockDisplay(dpy);
199      SyncHandle();
200      return(XvBadAlloc);
201  }
202  _XRead (dpy, buffer, size);
203
204  u.buffer = buffer;
205
206  /* GET INPUT ADAPTORS */
207
208  if (rep.num_adaptors == 0) {
209      pas = NULL;
210  } else {
211      size = rep.num_adaptors*sizeof(XvAdaptorInfo);
212      if ((pas=(XvAdaptorInfo *)Xmalloc(size))==NULL) {
213          Xfree(buffer);
214          UnlockDisplay(dpy);
215          SyncHandle();
216          return(XvBadAlloc);
217      }
218  }
219
220  /* INIT ADAPTOR FIELDS */
221
222  pa = pas;
223  for (ii=0; ii<rep.num_adaptors; ii++) {
224      pa->num_adaptors = 0;
225      pa->name = (char *)NULL;
226      pa->formats = (XvFormat *)NULL;
227      pa++;
228  }
229
230  pa = pas;
231  for (ii=0; ii<rep.num_adaptors; ii++) {
232      pa->type = u.pa->type;
233      pa->base_id = u.pa->base_id;
234      pa->num_ports = u.pa->num_ports;
235      pa->num_formats = u.pa->num_formats;
236      pa->num_adaptors = rep.num_adaptors - ii;
237
238      /* GET ADAPTOR NAME */
239
240      size = u.pa->name_size;
241      u.buffer += (sz_xvAdaptorInfo + 3) & ~3;
242
243      if ( (name = (char *)Xmalloc(size+1)) == NULL)
244	{
245	  XvFreeAdaptorInfo(pas);
246	  Xfree(buffer);
247          UnlockDisplay(dpy);
248          SyncHandle();
249	  return(XvBadAlloc);
250	}
251      (void)strncpy(name, u.string, size);
252      name[size] = '\0';
253      pa->name = name;
254
255      u.buffer += (size + 3) & ~3;
256
257      /* GET FORMATS */
258
259      size = pa->num_formats*sizeof(XvFormat);
260      if ((pfs=(XvFormat *)Xmalloc(size))==NULL) {
261	  XvFreeAdaptorInfo(pas);
262	  Xfree(buffer);
263          UnlockDisplay(dpy);
264          SyncHandle();
265	  return(XvBadAlloc);
266      }
267
268      pf = pfs;
269      for (jj=0; jj<pa->num_formats; jj++) {
270	  pf->depth = u.pf->depth;
271	  pf->visual_id = u.pf->visual;
272	  pf++;
273
274	  u.buffer += (sz_xvFormat + 3) & ~3;
275      }
276
277      pa->formats = pfs;
278
279      pa++;
280
281  }
282
283  *p_nAdaptors = rep.num_adaptors;
284  *p_pAdaptors = pas;
285
286  Xfree(buffer);
287  UnlockDisplay(dpy);
288  SyncHandle();
289
290  return (Success);
291}
292
293
294void
295XvFreeAdaptorInfo(XvAdaptorInfo *pAdaptors)
296{
297
298  XvAdaptorInfo *pa;
299  int ii;
300
301  if (!pAdaptors) return;
302
303  pa = pAdaptors;
304
305  for (ii=0; ii<pAdaptors->num_adaptors; ii++, pa++)
306    {
307      if (pa->name)
308	{
309	  Xfree(pa->name);
310	}
311      if (pa->formats)
312	{
313	  Xfree(pa->formats);
314	}
315    }
316
317  Xfree(pAdaptors);
318}
319
320int
321XvQueryEncodings(
322     Display *dpy,
323     XvPortID port,
324     unsigned int *p_nEncodings,
325     XvEncodingInfo **p_pEncodings
326){
327  XExtDisplayInfo *info = xv_find_display(dpy);
328  xvQueryEncodingsReq *req;
329  xvQueryEncodingsReply rep;
330  int size, jj;
331  char *name;
332  XvEncodingInfo *pes, *pe;
333  char *buffer;
334  union
335    {
336      char *buffer;
337      char *string;
338      xvEncodingInfo *pe;
339    } u;
340
341  XvCheckExtension(dpy, info, XvBadExtension);
342
343  LockDisplay(dpy);
344
345  XvGetReq(QueryEncodings, req);
346  req->port = port;
347
348  /* READ THE REPLY */
349
350  if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) {
351      UnlockDisplay(dpy);
352      SyncHandle();
353      return(XvBadReply);
354  }
355
356  size = rep.length << 2;
357  if ( (buffer = (char *)Xmalloc ((unsigned) size)) == NULL) {
358      UnlockDisplay(dpy);
359      SyncHandle();
360      return(XvBadAlloc);
361  }
362  _XRead (dpy, buffer, size);
363
364  u.buffer = buffer;
365
366  /* GET ENCODINGS */
367
368  size = rep.num_encodings*sizeof(XvEncodingInfo);
369  if ( (pes = (XvEncodingInfo *)Xmalloc(size)) == NULL) {
370      Xfree(buffer);
371      UnlockDisplay(dpy);
372      SyncHandle();
373      return(XvBadAlloc);
374  }
375
376  /* INITIALIZE THE ENCODING POINTER */
377
378  pe = pes;
379  for (jj=0; jj<rep.num_encodings; jj++) {
380      pe->name = (char *)NULL;
381      pe->num_encodings = 0;
382      pe++;
383  }
384
385  pe = pes;
386  for (jj=0; jj<rep.num_encodings; jj++) {
387      pe->encoding_id = u.pe->encoding;
388      pe->width = u.pe->width;
389      pe->height = u.pe->height;
390      pe->rate.numerator = u.pe->rate.numerator;
391      pe->rate.denominator = u.pe->rate.denominator;
392      pe->num_encodings = rep.num_encodings - jj;
393
394      size = u.pe->name_size;
395      u.buffer += (sz_xvEncodingInfo + 3) & ~3;
396
397      if ( (name = (char *)Xmalloc(size+1)) == NULL) {
398	  XvFreeEncodingInfo(pes);
399	  Xfree(buffer);
400          UnlockDisplay(dpy);
401          SyncHandle();
402	  return(XvBadAlloc);
403      }
404      strncpy(name, u.string, size);
405      name[size] = '\0';
406      pe->name = name;
407      pe++;
408
409      u.buffer += (size + 3) & ~3;
410  }
411
412  *p_nEncodings = rep.num_encodings;
413  *p_pEncodings = pes;
414
415  Xfree(buffer);
416  UnlockDisplay(dpy);
417  SyncHandle();
418
419  return (Success);
420}
421
422void
423XvFreeEncodingInfo(XvEncodingInfo *pEncodings)
424{
425
426  XvEncodingInfo *pe;
427  int ii;
428
429  if (!pEncodings) return;
430
431  pe = pEncodings;
432
433  for (ii=0; ii<pEncodings->num_encodings; ii++, pe++) {
434      if (pe->name) Xfree(pe->name);
435  }
436
437  Xfree(pEncodings);
438}
439
440int
441XvPutVideo(
442     Display *dpy,
443     XvPortID port,
444     Drawable d,
445     GC gc,
446     int vx, int vy,
447     unsigned int vw, unsigned int vh,
448     int dx, int dy,
449     unsigned int dw, unsigned int dh
450){
451  XExtDisplayInfo *info = xv_find_display(dpy);
452  xvPutVideoReq *req;
453
454  XvCheckExtension(dpy, info, XvBadExtension);
455
456  LockDisplay(dpy);
457
458  FlushGC(dpy, gc);
459
460  XvGetReq(PutVideo, req);
461
462  req->port = port;
463  req->drawable = d;
464  req->gc = gc->gid;
465  req->vid_x = vx;
466  req->vid_y = vy;
467  req->vid_w = vw;
468  req->vid_h = vh;
469  req->drw_x = dx;
470  req->drw_y = dy;
471  req->drw_w = dw;
472  req->drw_h = dh;
473
474  UnlockDisplay(dpy);
475  SyncHandle();
476
477  return Success;
478}
479
480int
481XvPutStill(
482     Display *dpy,
483     XvPortID port,
484     Drawable d,
485     GC gc,
486     int vx, int vy,
487     unsigned int vw, unsigned int vh,
488     int dx, int dy,
489     unsigned int dw, unsigned int dh
490){
491  XExtDisplayInfo *info = xv_find_display(dpy);
492  xvPutStillReq *req;
493
494  XvCheckExtension(dpy, info, XvBadExtension);
495
496  LockDisplay(dpy);
497
498  FlushGC(dpy, gc);
499
500  XvGetReq(PutStill, req);
501  req->port = port;
502  req->drawable = d;
503  req->gc = gc->gid;
504  req->vid_x = vx;
505  req->vid_y = vy;
506  req->vid_w = vw;
507  req->vid_h = vh;
508  req->drw_x = dx;
509  req->drw_y = dy;
510  req->drw_w = dw;
511  req->drw_h = dh;
512
513  UnlockDisplay(dpy);
514  SyncHandle();
515
516  return Success;
517}
518
519int
520XvGetVideo(
521     Display *dpy,
522     XvPortID port,
523     Drawable d,
524     GC gc,
525     int vx, int vy,
526     unsigned int vw, unsigned int vh,
527     int dx, int dy,
528     unsigned int dw, unsigned int dh
529){
530  XExtDisplayInfo *info = xv_find_display(dpy);
531  xvGetVideoReq *req;
532
533  XvCheckExtension(dpy, info, XvBadExtension);
534
535  LockDisplay(dpy);
536
537  FlushGC(dpy, gc);
538
539  XvGetReq(GetVideo, req);
540  req->port = port;
541  req->drawable = d;
542  req->gc = gc->gid;
543  req->vid_x = vx;
544  req->vid_y = vy;
545  req->vid_w = vw;
546  req->vid_h = vh;
547  req->drw_x = dx;
548  req->drw_y = dy;
549  req->drw_w = dw;
550  req->drw_h = dh;
551
552  UnlockDisplay(dpy);
553  SyncHandle();
554
555  return Success;
556}
557
558int
559XvGetStill(
560     Display *dpy,
561     XvPortID port,
562     Drawable d,
563     GC gc,
564     int vx, int vy,
565     unsigned int vw, unsigned int vh,
566     int dx, int dy,
567     unsigned int dw, unsigned int dh
568){
569  XExtDisplayInfo *info = xv_find_display(dpy);
570  xvGetStillReq *req;
571
572  XvCheckExtension(dpy, info, XvBadExtension);
573
574  LockDisplay(dpy);
575
576  FlushGC(dpy, gc);
577
578  XvGetReq(GetStill, req);
579  req->port = port;
580  req->drawable = d;
581  req->gc = gc->gid;
582  req->vid_x = vx;
583  req->vid_y = vy;
584  req->vid_w = vw;
585  req->vid_h = vh;
586  req->drw_x = dx;
587  req->drw_y = dy;
588  req->drw_w = dw;
589  req->drw_h = dh;
590
591  UnlockDisplay(dpy);
592  SyncHandle();
593
594  return Success;
595}
596
597int
598XvStopVideo(
599     Display *dpy,
600     XvPortID port,
601     Drawable draw
602){
603  XExtDisplayInfo *info = xv_find_display(dpy);
604  xvStopVideoReq *req;
605
606  XvCheckExtension(dpy, info, XvBadExtension);
607
608  LockDisplay(dpy);
609
610  XvGetReq(StopVideo, req);
611  req->port = port;
612  req->drawable = draw;
613
614  UnlockDisplay(dpy);
615  SyncHandle();
616
617  return Success;
618}
619
620int
621XvGrabPort(
622     Display *dpy,
623     XvPortID port,
624     Time time
625){
626  XExtDisplayInfo *info = xv_find_display(dpy);
627  int result;
628  xvGrabPortReply rep;
629  xvGrabPortReq *req;
630
631  XvCheckExtension(dpy, info, XvBadExtension);
632
633  LockDisplay(dpy);
634
635  XvGetReq(GrabPort, req);
636  req->port = port;
637  req->time = time;
638
639  if (_XReply (dpy, (xReply *) &rep, 0, xTrue) == 0)
640    rep.result = GrabSuccess;
641
642  result = rep.result;
643
644  UnlockDisplay(dpy);
645  SyncHandle();
646
647  return result;
648}
649
650int
651XvUngrabPort(
652     Display *dpy,
653     XvPortID port,
654     Time time
655){
656  XExtDisplayInfo *info = xv_find_display(dpy);
657  xvUngrabPortReq *req;
658
659  XvCheckExtension(dpy, info, XvBadExtension);
660
661  LockDisplay(dpy);
662
663  XvGetReq(UngrabPort, req);
664  req->port = port;
665  req->time = time;
666
667  UnlockDisplay(dpy);
668  SyncHandle();
669
670  return Success;
671}
672
673int
674XvSelectVideoNotify(
675     Display *dpy,
676     Drawable drawable,
677     Bool onoff
678){
679  XExtDisplayInfo *info = xv_find_display(dpy);
680  xvSelectVideoNotifyReq *req;
681
682  XvCheckExtension(dpy, info, XvBadExtension);
683
684  LockDisplay(dpy);
685
686  XvGetReq(SelectVideoNotify, req);
687  req->drawable = drawable;
688  req->onoff = onoff;
689
690  UnlockDisplay(dpy);
691  SyncHandle();
692
693  return Success;
694}
695
696int
697XvSelectPortNotify(
698     Display *dpy,
699     XvPortID port,
700     Bool onoff
701){
702  XExtDisplayInfo *info = xv_find_display(dpy);
703  xvSelectPortNotifyReq *req;
704
705  XvCheckExtension(dpy, info, XvBadExtension);
706
707  LockDisplay(dpy);
708
709  XvGetReq(SelectPortNotify, req);
710  req->port = port;
711  req->onoff = onoff;
712
713  UnlockDisplay(dpy);
714  SyncHandle();
715
716  return Success;
717}
718
719int
720XvSetPortAttribute (
721     Display *dpy,
722     XvPortID port,
723     Atom attribute,
724     int value
725)
726{
727  XExtDisplayInfo *info = xv_find_display(dpy);
728  xvSetPortAttributeReq *req;
729
730  XvCheckExtension(dpy, info, XvBadExtension);
731
732  LockDisplay(dpy);
733
734  XvGetReq(SetPortAttribute, req);
735  req->port = port;
736  req->attribute = attribute;
737  req->value = value;
738
739  UnlockDisplay(dpy);
740  SyncHandle();
741
742  return (Success);
743}
744
745int
746XvGetPortAttribute (
747     Display *dpy,
748     XvPortID port,
749     Atom attribute,
750     int *p_value
751)
752{
753  XExtDisplayInfo *info = xv_find_display(dpy);
754  xvGetPortAttributeReq *req;
755  xvGetPortAttributeReply rep;
756
757  XvCheckExtension(dpy, info, XvBadExtension);
758
759  LockDisplay(dpy);
760
761  XvGetReq(GetPortAttribute, req);
762  req->port = port;
763  req->attribute = attribute;
764
765  /* READ THE REPLY */
766
767  if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) {
768      UnlockDisplay(dpy);
769      SyncHandle();
770      return(XvBadReply);
771  }
772
773  *p_value = rep.value;
774
775  UnlockDisplay(dpy);
776  SyncHandle();
777
778  return (Success);
779}
780
781int
782XvQueryBestSize(
783     Display *dpy,
784     XvPortID port,
785     Bool motion,
786     unsigned int vid_w,
787     unsigned int vid_h,
788     unsigned int drw_w,
789     unsigned int drw_h,
790     unsigned int *p_actual_width,
791     unsigned int *p_actual_height
792)
793{
794  XExtDisplayInfo *info = xv_find_display(dpy);
795  xvQueryBestSizeReq *req;
796  xvQueryBestSizeReply rep;
797
798  XvCheckExtension(dpy, info, XvBadExtension);
799
800  LockDisplay(dpy);
801
802  XvGetReq(QueryBestSize, req);
803  req->port = port;
804  req->motion = motion;
805  req->vid_w = vid_w;
806  req->vid_h = vid_h;
807  req->drw_w = drw_w;
808  req->drw_h = drw_h;
809
810  /* READ THE REPLY */
811
812  if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) {
813      UnlockDisplay(dpy);
814      SyncHandle();
815      return(XvBadReply);
816  }
817
818  *p_actual_width = rep.actual_width;
819  *p_actual_height = rep.actual_height;
820
821  UnlockDisplay(dpy);
822  SyncHandle();
823
824  return (Success);
825}
826
827
828XvAttribute*
829XvQueryPortAttributes(Display *dpy, XvPortID port, int *num)
830{
831  XExtDisplayInfo *info = xv_find_display(dpy);
832  xvQueryPortAttributesReq *req;
833  xvQueryPortAttributesReply rep;
834  XvAttribute *ret = NULL;
835
836  *num = 0;
837
838  XvCheckExtension(dpy, info, NULL);
839
840  LockDisplay(dpy);
841
842  XvGetReq(QueryPortAttributes, req);
843  req->port = port;
844
845  /* READ THE REPLY */
846
847  if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) {
848      UnlockDisplay(dpy);
849      SyncHandle();
850      return ret;
851  }
852
853  if(rep.num_attributes) {
854      unsigned long size;
855      /* limit each part to no more than one half the max size */
856      if ((rep.num_attributes < ((INT_MAX / 2) / sizeof(XvAttribute))) &&
857	  (rep.text_size < (INT_MAX / 2))) {
858	  size = (rep.num_attributes * sizeof(XvAttribute)) + rep.text_size;
859	  ret = Xmalloc(size);
860      }
861
862      if (ret != NULL) {
863	  char* marker = (char*)(&ret[rep.num_attributes]);
864	  xvAttributeInfo Info;
865	  int i;
866
867	  /* keep track of remaining room for text strings */
868	  size = rep.text_size;
869
870	  for(i = 0; i < rep.num_attributes; i++) {
871             _XRead(dpy, (char*)(&Info), sz_xvAttributeInfo);
872	      ret[i].flags = (int)Info.flags;
873	      ret[i].min_value = Info.min;
874	      ret[i].max_value = Info.max;
875	      ret[i].name = marker;
876	      if (Info.size <= size) {
877		  _XRead(dpy, marker, Info.size);
878		  marker += Info.size;
879		  size -= Info.size;
880	      }
881	      (*num)++;
882	  }
883      } else
884	  _XEatDataWords(dpy, rep.length);
885  }
886
887  UnlockDisplay(dpy);
888  SyncHandle();
889
890  return ret;
891}
892
893XvImageFormatValues * XvListImageFormats (
894   Display 	*dpy,
895   XvPortID 	port,
896   int 		*num
897){
898  XExtDisplayInfo *info = xv_find_display(dpy);
899  xvListImageFormatsReq *req;
900  xvListImageFormatsReply rep;
901  XvImageFormatValues *ret = NULL;
902
903  *num = 0;
904
905  XvCheckExtension(dpy, info, NULL);
906
907  LockDisplay(dpy);
908
909  XvGetReq(ListImageFormats, req);
910  req->port = port;
911
912  /* READ THE REPLY */
913
914  if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) {
915      UnlockDisplay(dpy);
916      SyncHandle();
917      return NULL;
918  }
919
920  if(rep.num_formats) {
921      if (rep.num_formats < (INT_MAX / sizeof(XvImageFormatValues)))
922	  ret = Xmalloc(rep.num_formats * sizeof(XvImageFormatValues));
923
924      if (ret != NULL) {
925	  xvImageFormatInfo Info;
926	  int i;
927
928	  for(i = 0; i < rep.num_formats; i++) {
929              _XRead(dpy, (char*)(&Info), sz_xvImageFormatInfo);
930	      ret[i].id = Info.id;
931	      ret[i].type = Info.type;
932	      ret[i].byte_order = Info.byte_order;
933	      memcpy(&(ret[i].guid[0]), &(Info.guid[0]), 16);
934	      ret[i].bits_per_pixel = Info.bpp;
935  	      ret[i].format = Info.format;
936   	      ret[i].num_planes = Info.num_planes;
937    	      ret[i].depth = Info.depth;
938    	      ret[i].red_mask = Info.red_mask;
939    	      ret[i].green_mask = Info.green_mask;
940    	      ret[i].blue_mask = Info.blue_mask;
941    	      ret[i].y_sample_bits = Info.y_sample_bits;
942    	      ret[i].u_sample_bits = Info.u_sample_bits;
943    	      ret[i].v_sample_bits = Info.v_sample_bits;
944    	      ret[i].horz_y_period = Info.horz_y_period;
945    	      ret[i].horz_u_period = Info.horz_u_period;
946    	      ret[i].horz_v_period = Info.horz_v_period;
947    	      ret[i].vert_y_period = Info.vert_y_period;
948    	      ret[i].vert_u_period = Info.vert_u_period;
949    	      ret[i].vert_v_period = Info.vert_v_period;
950	      memcpy(&(ret[i].component_order[0]), &(Info.comp_order[0]), 32);
951    	      ret[i].scanline_order = Info.scanline_order;
952	      (*num)++;
953	  }
954      } else
955	  _XEatDataWords(dpy, rep.length);
956  }
957
958  UnlockDisplay(dpy);
959  SyncHandle();
960
961  return ret;
962}
963
964XvImage * XvCreateImage (
965   Display *dpy,
966   XvPortID port,
967   int id,
968   char *data,
969   int width,
970   int height
971) {
972   XExtDisplayInfo *info = xv_find_display(dpy);
973   xvQueryImageAttributesReq *req;
974   xvQueryImageAttributesReply rep;
975   XvImage *ret = NULL;
976
977   XvCheckExtension(dpy, info, NULL);
978
979   LockDisplay(dpy);
980
981   XvGetReq(QueryImageAttributes, req);
982   req->id = id;
983   req->port = port;
984   req->width = width;
985   req->height = height;
986
987   /* READ THE REPLY */
988
989   if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
990       UnlockDisplay(dpy);
991       SyncHandle();
992      return NULL;
993   }
994
995   if (rep.num_planes < ((INT_MAX >> 3) - sizeof(XvImage)))
996       ret = Xmalloc(sizeof(XvImage) + (rep.num_planes << 3));
997
998   if (ret != NULL) {
999	ret->id = id;
1000	ret->width = rep.width;
1001	ret->height = rep.height;
1002	ret->data_size = rep.data_size;
1003	ret->num_planes = rep.num_planes;
1004	ret->pitches = (int*)(&ret[1]);
1005	ret->offsets = ret->pitches + rep.num_planes;
1006	ret->data = data;
1007	ret->obdata = NULL;
1008  	_XRead(dpy, (char*)(ret->pitches), rep.num_planes << 2);
1009	_XRead(dpy, (char*)(ret->offsets), rep.num_planes << 2);
1010   } else
1011       _XEatDataWords(dpy, rep.length);
1012
1013   UnlockDisplay(dpy);
1014   SyncHandle();
1015
1016   return ret;
1017}
1018
1019XvImage * XvShmCreateImage (
1020   Display *dpy,
1021   XvPortID port,
1022   int id,
1023   char *data,
1024   int width,
1025   int height,
1026   XShmSegmentInfo *shminfo
1027){
1028   XvImage *ret;
1029
1030   ret = XvCreateImage(dpy, port, id, data, width, height);
1031
1032   if(ret) ret->obdata = (XPointer)shminfo;
1033
1034   return ret;
1035}
1036
1037int XvPutImage (
1038   Display *dpy,
1039   XvPortID port,
1040   Drawable d,
1041   GC gc,
1042   XvImage *image,
1043   int src_x,
1044   int src_y,
1045   unsigned int src_w,
1046   unsigned int src_h,
1047   int dest_x,
1048   int dest_y,
1049   unsigned int dest_w,
1050   unsigned int dest_h
1051){
1052  XExtDisplayInfo *info = xv_find_display(dpy);
1053  xvPutImageReq *req;
1054  int len;
1055
1056  XvCheckExtension(dpy, info, XvBadExtension);
1057
1058  LockDisplay(dpy);
1059
1060  FlushGC(dpy, gc);
1061
1062  XvGetReq(PutImage, req);
1063
1064  req->port = port;
1065  req->drawable = d;
1066  req->gc = gc->gid;
1067  req->id = image->id;
1068  req->src_x = src_x;
1069  req->src_y = src_y;
1070  req->src_w = src_w;
1071  req->src_h = src_h;
1072  req->drw_x = dest_x;
1073  req->drw_y = dest_y;
1074  req->drw_w = dest_w;
1075  req->drw_h = dest_h;
1076  req->width = image->width;
1077  req->height = image->height;
1078
1079  len = (image->data_size + 3) >> 2;
1080  SetReqLen(req, len, len);
1081
1082  /* Yes it's kindof lame that we are sending the whole thing,
1083     but for video all of it may be needed even if displaying
1084     only a subsection, and I don't want to go through the
1085     trouble of creating subregions to send */
1086  Data(dpy, (char *)image->data, image->data_size);
1087
1088  UnlockDisplay(dpy);
1089  SyncHandle();
1090
1091  return Success;
1092}
1093
1094int XvShmPutImage (
1095   Display *dpy,
1096   XvPortID port,
1097   Drawable d,
1098   GC gc,
1099   XvImage *image,
1100   int src_x,
1101   int src_y,
1102   unsigned int src_w,
1103   unsigned int src_h,
1104   int dest_x,
1105   int dest_y,
1106   unsigned int dest_w,
1107   unsigned int dest_h,
1108   Bool send_event
1109){
1110  XExtDisplayInfo *info = xv_find_display(dpy);
1111  XShmSegmentInfo *shminfo = (XShmSegmentInfo *)image->obdata;
1112  xvShmPutImageReq *req;
1113
1114  XvCheckExtension(dpy, info, XvBadExtension);
1115
1116  LockDisplay(dpy);
1117
1118  FlushGC(dpy, gc);
1119
1120  XvGetReq(ShmPutImage, req);
1121
1122  req->port = port;
1123  req->drawable = d;
1124  req->gc = gc->gid;
1125  req->shmseg = shminfo->shmseg;
1126  req->id = image->id;
1127  req->src_x = src_x;
1128  req->src_y = src_y;
1129  req->src_w = src_w;
1130  req->src_h = src_h;
1131  req->drw_x = dest_x;
1132  req->drw_y = dest_y;
1133  req->drw_w = dest_w;
1134  req->drw_h = dest_h;
1135  req->offset = image->data - shminfo->shmaddr;
1136  req->width = image->width;
1137  req->height = image->height;
1138  req->send_event = send_event;
1139
1140  UnlockDisplay(dpy);
1141  SyncHandle();
1142
1143  return Success;
1144}
1145
1146
1147static Bool
1148xv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire)
1149{
1150  XExtDisplayInfo *info = xv_find_display(dpy);
1151  XvEvent *re    = (XvEvent *)host;
1152  xvEvent *event = (xvEvent *)wire;
1153
1154  XvCheckExtension(dpy, info, False);
1155
1156  switch((event->u.u.type & 0x7F) - info->codes->first_event)
1157  {
1158    case XvVideoNotify:
1159      re->xvvideo.type = event->u.u.type & 0x7f;
1160      re->xvvideo.serial =
1161	_XSetLastRequestRead(dpy, (xGenericReply *)event);
1162      re->xvvideo.send_event = ((event->u.u.type & 0x80) != 0);
1163      re->xvvideo.display = dpy;
1164      re->xvvideo.time = event->u.videoNotify.time;
1165      re->xvvideo.reason = event->u.videoNotify.reason;
1166      re->xvvideo.drawable = event->u.videoNotify.drawable;
1167      re->xvvideo.port_id = event->u.videoNotify.port;
1168      break;
1169    case XvPortNotify:
1170      re->xvport.type = event->u.u.type & 0x7f;
1171      re->xvport.serial =
1172	_XSetLastRequestRead(dpy, (xGenericReply *)event);
1173      re->xvport.send_event = ((event->u.u.type & 0x80) != 0);
1174      re->xvport.display = dpy;
1175      re->xvport.time = event->u.portNotify.time;
1176      re->xvport.port_id = event->u.portNotify.port;
1177      re->xvport.attribute = event->u.portNotify.attribute;
1178      re->xvport.value = event->u.portNotify.value;
1179      break;
1180    default:
1181      return False;
1182  }
1183
1184  return (True);
1185}
1186
1187
1188