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