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