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