Xv.c revision fef5d1ff
19f606849Smrg/***********************************************************
29f606849SmrgCopyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts,
39f606849Smrgand the Massachusetts Institute of Technology, Cambridge, Massachusetts.
49f606849Smrg
59f606849Smrg                        All Rights Reserved
69f606849Smrg
7cdbfa18aSmrgPermission to use, copy, modify, and distribute this software and its
8cdbfa18aSmrgdocumentation for any purpose and without fee is hereby granted,
99f606849Smrgprovided that the above copyright notice appear in all copies and that
10cdbfa18aSmrgboth that copyright notice and this permission notice appear in
119f606849Smrgsupporting documentation, and that the names of Digital or MIT not be
129f606849Smrgused in advertising or publicity pertaining to distribution of the
13cdbfa18aSmrgsoftware without specific, written prior permission.
149f606849Smrg
159f606849SmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
169f606849SmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
179f606849SmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
189f606849SmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
199f606849SmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
209f606849SmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
219f606849SmrgSOFTWARE.
229f606849Smrg
239f606849Smrg******************************************************************/
249f606849Smrg/*
25cdbfa18aSmrg** File:
269f606849Smrg**
279f606849Smrg**   Xv.c --- Xv library extension module.
289f606849Smrg**
29cdbfa18aSmrg** Author:
309f606849Smrg**
319f606849Smrg**   David Carver (Digital Workstation Engineering/Project Athena)
329f606849Smrg**
339f606849Smrg** Revisions:
349f606849Smrg**
359f606849Smrg**   26.06.91 Carver
369f606849Smrg**     - changed XvFreeAdaptors to XvFreeAdaptorInfo
379f606849Smrg**     - changed XvFreeEncodings to XvFreeEncodingInfo
389f606849Smrg**
399f606849Smrg**   11.06.91 Carver
409f606849Smrg**     - changed SetPortControl to SetPortAttribute
419f606849Smrg**     - changed GetPortControl to GetPortAttribute
429f606849Smrg**     - changed QueryBestSize
439f606849Smrg**
449f606849Smrg**   15.05.91 Carver
459f606849Smrg**     - version 2.0 upgrade
469f606849Smrg**
479f606849Smrg**   240.01.91 Carver
489f606849Smrg**     - version 1.4 upgrade
499f606849Smrg**
509f606849Smrg*/
519f606849Smrg
52cdbfa18aSmrg#ifdef HAVE_CONFIG_H
53cdbfa18aSmrg# include "config.h"
54cdbfa18aSmrg#endif
55cdbfa18aSmrg
569f606849Smrg#include <stdio.h>
579f606849Smrg#include "Xvlibint.h"
589f606849Smrg#include <X11/extensions/Xext.h>
599f606849Smrg#include <X11/extensions/extutil.h>
609f606849Smrg#include <X11/extensions/XShm.h>
61cdbfa18aSmrg#include <limits.h>
62cdbfa18aSmrg
639f606849Smrgstatic XExtensionInfo _xv_info_data;
649f606849Smrgstatic XExtensionInfo *xv_info = &_xv_info_data;
65cdbfa18aSmrgstatic const char *xv_extension_name = XvName;
669f606849Smrg
679f606849Smrg#define XvCheckExtension(dpy, i, val) \
689f606849Smrg  XextCheckExtension(dpy, i, xv_extension_name, val)
699f606849Smrg
70fef5d1ffSmrg#define pad_to_int32(bytes) (((bytes) + 3) & ~3U)
71fef5d1ffSmrg
729f606849Smrgstatic char *xv_error_string(Display *dpy, int code, XExtCodes *codes,
73fef5d1ffSmrg                             char *buf, int n);
749f606849Smrgstatic int xv_close_display(Display *dpy, XExtCodes *codes);
759f606849Smrgstatic Bool xv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire);
769f606849Smrg
779f606849Smrgstatic XExtensionHooks xv_extension_hooks = {
78fef5d1ffSmrg    NULL,                       /* create_gc */
79fef5d1ffSmrg    NULL,                       /* copy_gc */
80fef5d1ffSmrg    NULL,                       /* flush_gc */
81fef5d1ffSmrg    NULL,                       /* free_gc */
82fef5d1ffSmrg    NULL,                       /* create_font */
83fef5d1ffSmrg    NULL,                       /* free_font */
84fef5d1ffSmrg    xv_close_display,           /* close_display */
85fef5d1ffSmrg    xv_wire_to_event,           /* wire_to_event */
86fef5d1ffSmrg    NULL,                       /* event_to_wire */
87fef5d1ffSmrg    NULL,                       /* error */
88fef5d1ffSmrg    xv_error_string             /* error_string */
899f606849Smrg};
909f606849Smrg
919f606849Smrg
92fef5d1ffSmrgstatic const char *xv_error_list[] = {
93fef5d1ffSmrg    "BadPort",                  /* XvBadPort     */
94fef5d1ffSmrg    "BadEncoding",              /* XvBadEncoding */
95fef5d1ffSmrg    "BadControl"                /* XvBadControl  */
969f606849Smrg};
979f606849Smrg
98fef5d1ffSmrgstatic XEXT_GENERATE_CLOSE_DISPLAY(xv_close_display, xv_info)
999f606849Smrg
100fef5d1ffSmrgstatic XEXT_GENERATE_FIND_DISPLAY(xv_find_display, xv_info,
101fef5d1ffSmrg				  xv_extension_name, &xv_extension_hooks,
102fef5d1ffSmrg				  XvNumEvents, NULL)
1039f606849Smrg
104fef5d1ffSmrgstatic XEXT_GENERATE_ERROR_STRING(xv_error_string, xv_extension_name,
105fef5d1ffSmrg				  XvNumErrors, xv_error_list)
1069f606849Smrg
1079f606849Smrg
1089f606849Smrgint
1099f606849SmrgXvQueryExtension(
110fef5d1ffSmrg    Display *dpy,
111fef5d1ffSmrg    unsigned int *p_version,
112fef5d1ffSmrg    unsigned int *p_revision,
113fef5d1ffSmrg    unsigned int *p_requestBase,
114fef5d1ffSmrg    unsigned int *p_eventBase,
115fef5d1ffSmrg    unsigned int *p_errorBase)
116fef5d1ffSmrg{
117fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
118fef5d1ffSmrg    xvQueryExtensionReq *req;
119fef5d1ffSmrg    xvQueryExtensionReply rep;
120fef5d1ffSmrg    int status;
121fef5d1ffSmrg
122fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
123fef5d1ffSmrg
124fef5d1ffSmrg    LockDisplay(dpy);
125fef5d1ffSmrg
126fef5d1ffSmrg    XvGetReq(QueryExtension, req);
127fef5d1ffSmrg
128fef5d1ffSmrg    if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
129fef5d1ffSmrg        status = XvBadExtension;
130fef5d1ffSmrg        goto out;
131fef5d1ffSmrg    }
132fef5d1ffSmrg
133fef5d1ffSmrg    *p_version = rep.version;
134fef5d1ffSmrg    *p_revision = rep.revision;
135fef5d1ffSmrg    *p_requestBase = info->codes->major_opcode;
136fef5d1ffSmrg    *p_eventBase = info->codes->first_event;
137fef5d1ffSmrg    *p_errorBase = info->codes->first_error;
138fef5d1ffSmrg
139fef5d1ffSmrg    status = Success;
140fef5d1ffSmrg
141fef5d1ffSmrg  out:
142fef5d1ffSmrg    UnlockDisplay(dpy);
143fef5d1ffSmrg    SyncHandle();
144fef5d1ffSmrg
145fef5d1ffSmrg    return status;
1469f606849Smrg}
1479f606849Smrg
1489f606849Smrgint
1499f606849SmrgXvQueryAdaptors(
150fef5d1ffSmrg    Display *dpy,
151fef5d1ffSmrg    Window window,
152fef5d1ffSmrg    unsigned int *p_nAdaptors,
153fef5d1ffSmrg    XvAdaptorInfo **p_pAdaptors)
154fef5d1ffSmrg{
155fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
156fef5d1ffSmrg    xvQueryAdaptorsReq *req;
157fef5d1ffSmrg    xvQueryAdaptorsReply rep;
158fef5d1ffSmrg    size_t size;
159fef5d1ffSmrg    unsigned int ii, jj;
160fef5d1ffSmrg    char *name;
161fef5d1ffSmrg    XvAdaptorInfo *pas = NULL, *pa;
162fef5d1ffSmrg    XvFormat *pfs, *pf;
163fef5d1ffSmrg    char *buffer = NULL;
164fef5d1ffSmrg    union {
165fef5d1ffSmrg        char *buffer;
166fef5d1ffSmrg        char *string;
167fef5d1ffSmrg        xvAdaptorInfo *pa;
168fef5d1ffSmrg        xvFormat *pf;
1699f606849Smrg    } u;
170fef5d1ffSmrg    int status;
171fef5d1ffSmrg
172fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
173fef5d1ffSmrg
174fef5d1ffSmrg    LockDisplay(dpy);
175fef5d1ffSmrg
176fef5d1ffSmrg    XvGetReq(QueryAdaptors, req);
177fef5d1ffSmrg    req->window = window;
178fef5d1ffSmrg
179fef5d1ffSmrg    /* READ THE REPLY */
180fef5d1ffSmrg
181fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) {
182fef5d1ffSmrg        rep.num_adaptors = 0;
183fef5d1ffSmrg        status = XvBadReply;
184fef5d1ffSmrg        goto out;
185fef5d1ffSmrg    }
186fef5d1ffSmrg
187fef5d1ffSmrg    size = rep.length << 2;
188fef5d1ffSmrg    if (size > 0) {
189fef5d1ffSmrg        if ((buffer = Xmalloc(size)) == NULL) {
190fef5d1ffSmrg            _XEatDataWords(dpy, rep.length);
191fef5d1ffSmrg            status = XvBadAlloc;
192fef5d1ffSmrg            goto out;
193fef5d1ffSmrg        }
194fef5d1ffSmrg        _XRead(dpy, buffer, (long) size);
195fef5d1ffSmrg    }
196fef5d1ffSmrg
197fef5d1ffSmrg    /* GET INPUT ADAPTORS */
198fef5d1ffSmrg
199fef5d1ffSmrg    if (rep.num_adaptors == 0) {
200fef5d1ffSmrg        /* If there's no adaptors, there's nothing more to do. */
201fef5d1ffSmrg        status = Success;
202fef5d1ffSmrg        goto out;
203fef5d1ffSmrg    }
204fef5d1ffSmrg
205fef5d1ffSmrg    if (size < (rep.num_adaptors * sz_xvAdaptorInfo)) {
206fef5d1ffSmrg        /* If there's not enough data for the number of adaptors,
207fef5d1ffSmrg           then we have a problem. */
208fef5d1ffSmrg        status = XvBadReply;
209fef5d1ffSmrg        goto out;
210fef5d1ffSmrg    }
211fef5d1ffSmrg
212fef5d1ffSmrg    size = rep.num_adaptors * sizeof(XvAdaptorInfo);
213fef5d1ffSmrg    if ((pas = Xmalloc(size)) == NULL) {
214fef5d1ffSmrg        status = XvBadAlloc;
215fef5d1ffSmrg        goto out;
216fef5d1ffSmrg    }
217fef5d1ffSmrg
218fef5d1ffSmrg    /* INIT ADAPTOR FIELDS */
219fef5d1ffSmrg
220fef5d1ffSmrg    pa = pas;
221fef5d1ffSmrg    for (ii = 0; ii < rep.num_adaptors; ii++) {
222fef5d1ffSmrg        pa->num_adaptors = 0;
223fef5d1ffSmrg        pa->name = (char *) NULL;
224fef5d1ffSmrg        pa->formats = (XvFormat *) NULL;
225fef5d1ffSmrg        pa++;
226fef5d1ffSmrg    }
227fef5d1ffSmrg
228fef5d1ffSmrg    u.buffer = buffer;
229fef5d1ffSmrg    pa = pas;
230fef5d1ffSmrg    for (ii = 0; ii < rep.num_adaptors; ii++) {
231fef5d1ffSmrg        pa->type = u.pa->type;
232fef5d1ffSmrg        pa->base_id = u.pa->base_id;
233fef5d1ffSmrg        pa->num_ports = u.pa->num_ports;
234fef5d1ffSmrg        pa->num_formats = u.pa->num_formats;
235fef5d1ffSmrg        pa->num_adaptors = rep.num_adaptors - ii;
236fef5d1ffSmrg
237fef5d1ffSmrg        /* GET ADAPTOR NAME */
238fef5d1ffSmrg
239fef5d1ffSmrg        size = u.pa->name_size;
240fef5d1ffSmrg        u.buffer += pad_to_int32(sz_xvAdaptorInfo);
241fef5d1ffSmrg
242fef5d1ffSmrg        if ((name = Xmalloc(size + 1)) == NULL) {
243fef5d1ffSmrg            status = XvBadAlloc;
244fef5d1ffSmrg            goto out;
245fef5d1ffSmrg        }
246fef5d1ffSmrg        (void) strncpy(name, u.string, size);
247fef5d1ffSmrg        name[size] = '\0';
248fef5d1ffSmrg        pa->name = name;
249fef5d1ffSmrg
250fef5d1ffSmrg        u.buffer += pad_to_int32(size);
251cdbfa18aSmrg
252fef5d1ffSmrg        /* GET FORMATS */
253fef5d1ffSmrg
254fef5d1ffSmrg        size = pa->num_formats * sizeof(XvFormat);
255fef5d1ffSmrg        if ((pfs = Xmalloc(size)) == NULL) {
256fef5d1ffSmrg            status = XvBadAlloc;
257fef5d1ffSmrg            goto out;
258fef5d1ffSmrg        }
259fef5d1ffSmrg
260fef5d1ffSmrg        pf = pfs;
261fef5d1ffSmrg        for (jj = 0; jj < pa->num_formats; jj++) {
262fef5d1ffSmrg            pf->depth = u.pf->depth;
263fef5d1ffSmrg            pf->visual_id = u.pf->visual;
264fef5d1ffSmrg            pf++;
265fef5d1ffSmrg
266fef5d1ffSmrg            u.buffer += pad_to_int32(sz_xvFormat);
267fef5d1ffSmrg        }
268fef5d1ffSmrg
269fef5d1ffSmrg        pa->formats = pfs;
270fef5d1ffSmrg
271fef5d1ffSmrg        pa++;
272fef5d1ffSmrg
273fef5d1ffSmrg    }
274fef5d1ffSmrg
275fef5d1ffSmrg    status = Success;
276fef5d1ffSmrg
277fef5d1ffSmrg  out:
278fef5d1ffSmrg    if (status != Success) {
279fef5d1ffSmrg        XvFreeAdaptorInfo(pas);
280fef5d1ffSmrg        pas = NULL;
281fef5d1ffSmrg    }
282fef5d1ffSmrg
283fef5d1ffSmrg    *p_nAdaptors = rep.num_adaptors;
284fef5d1ffSmrg    *p_pAdaptors = pas;
285fef5d1ffSmrg
286fef5d1ffSmrg    Xfree(buffer);
287fef5d1ffSmrg    UnlockDisplay(dpy);
288fef5d1ffSmrg    SyncHandle();
289fef5d1ffSmrg
290fef5d1ffSmrg    return status;
2919f606849Smrg}
2929f606849Smrg
2939f606849Smrg
2949f606849Smrgvoid
2959f606849SmrgXvFreeAdaptorInfo(XvAdaptorInfo *pAdaptors)
2969f606849Smrg{
297fef5d1ffSmrg    XvAdaptorInfo *pa;
298fef5d1ffSmrg    unsigned int ii;
2999f606849Smrg
300fef5d1ffSmrg    if (!pAdaptors)
301fef5d1ffSmrg        return;
3029f606849Smrg
303fef5d1ffSmrg    pa = pAdaptors;
3049f606849Smrg
305fef5d1ffSmrg    for (ii = 0; ii < pAdaptors->num_adaptors; ii++, pa++) {
306fef5d1ffSmrg        if (pa->name) {
307fef5d1ffSmrg            Xfree(pa->name);
308fef5d1ffSmrg        }
309fef5d1ffSmrg        if (pa->formats) {
310fef5d1ffSmrg            Xfree(pa->formats);
311fef5d1ffSmrg        }
312cdbfa18aSmrg    }
3139f606849Smrg
314fef5d1ffSmrg    Xfree(pAdaptors);
3159f606849Smrg}
3169f606849Smrg
3179f606849Smrgint
3189f606849SmrgXvQueryEncodings(
319fef5d1ffSmrg    Display *dpy,
320fef5d1ffSmrg    XvPortID port,
321fef5d1ffSmrg    unsigned int *p_nEncodings,
322fef5d1ffSmrg    XvEncodingInfo ** p_pEncodings)
323fef5d1ffSmrg{
324fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
325fef5d1ffSmrg    xvQueryEncodingsReq *req;
326fef5d1ffSmrg    xvQueryEncodingsReply rep;
327fef5d1ffSmrg    size_t size;
328fef5d1ffSmrg    unsigned int jj;
329fef5d1ffSmrg    char *name;
330fef5d1ffSmrg    XvEncodingInfo *pes = NULL, *pe;
331fef5d1ffSmrg    char *buffer = NULL;
332fef5d1ffSmrg    union {
333fef5d1ffSmrg        char *buffer;
334fef5d1ffSmrg        char *string;
335fef5d1ffSmrg        xvEncodingInfo *pe;
3369f606849Smrg    } u;
337fef5d1ffSmrg    int status;
338fef5d1ffSmrg
339fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
340fef5d1ffSmrg
341fef5d1ffSmrg    LockDisplay(dpy);
342fef5d1ffSmrg
343fef5d1ffSmrg    XvGetReq(QueryEncodings, req);
344fef5d1ffSmrg    req->port = port;
345fef5d1ffSmrg
346fef5d1ffSmrg    /* READ THE REPLY */
347fef5d1ffSmrg
348fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) {
349fef5d1ffSmrg        rep.num_encodings = 0;
350fef5d1ffSmrg        status = XvBadReply;
351fef5d1ffSmrg        goto out;
352fef5d1ffSmrg    }
353cdbfa18aSmrg
354fef5d1ffSmrg    size = rep.length << 2;
355fef5d1ffSmrg    if (size > 0) {
356fef5d1ffSmrg        if ((buffer = Xmalloc(size)) == NULL) {
357fef5d1ffSmrg            _XEatDataWords(dpy, rep.length);
358fef5d1ffSmrg            status = XvBadAlloc;
359fef5d1ffSmrg            goto out;
360fef5d1ffSmrg        }
361fef5d1ffSmrg        _XRead(dpy, buffer, (long) size);
362fef5d1ffSmrg    }
363fef5d1ffSmrg
364fef5d1ffSmrg    /* GET ENCODINGS */
365fef5d1ffSmrg
366fef5d1ffSmrg    if (rep.num_encodings == 0) {
367fef5d1ffSmrg        /* If there's no encodings, there's nothing more to do. */
368fef5d1ffSmrg        status = Success;
369fef5d1ffSmrg        goto out;
370fef5d1ffSmrg    }
371fef5d1ffSmrg
372fef5d1ffSmrg    if (size < (rep.num_encodings * sz_xvEncodingInfo)) {
373fef5d1ffSmrg        /* If there's not enough data for the number of adaptors,
374fef5d1ffSmrg           then we have a problem. */
375fef5d1ffSmrg        status = XvBadReply;
376fef5d1ffSmrg        goto out;
377fef5d1ffSmrg    }
378fef5d1ffSmrg
379fef5d1ffSmrg    size = rep.num_encodings * sizeof(XvEncodingInfo);
380fef5d1ffSmrg    if ((pes = Xmalloc(size)) == NULL) {
381fef5d1ffSmrg        status = XvBadAlloc;
382fef5d1ffSmrg        goto out;
383fef5d1ffSmrg    }
384fef5d1ffSmrg
385fef5d1ffSmrg    /* INITIALIZE THE ENCODING POINTER */
386fef5d1ffSmrg
387fef5d1ffSmrg    pe = pes;
388fef5d1ffSmrg    for (jj = 0; jj < rep.num_encodings; jj++) {
389fef5d1ffSmrg        pe->name = (char *) NULL;
390fef5d1ffSmrg        pe->num_encodings = 0;
391fef5d1ffSmrg        pe++;
392fef5d1ffSmrg    }
393fef5d1ffSmrg
394fef5d1ffSmrg    u.buffer = buffer;
395fef5d1ffSmrg
396fef5d1ffSmrg    pe = pes;
397fef5d1ffSmrg    for (jj = 0; jj < rep.num_encodings; jj++) {
398fef5d1ffSmrg        pe->encoding_id = u.pe->encoding;
399fef5d1ffSmrg        pe->width = u.pe->width;
400fef5d1ffSmrg        pe->height = u.pe->height;
401fef5d1ffSmrg        pe->rate.numerator = u.pe->rate.numerator;
402fef5d1ffSmrg        pe->rate.denominator = u.pe->rate.denominator;
403fef5d1ffSmrg        pe->num_encodings = rep.num_encodings - jj;
404fef5d1ffSmrg
405fef5d1ffSmrg        size = u.pe->name_size;
406fef5d1ffSmrg        u.buffer += pad_to_int32(sz_xvEncodingInfo);
407fef5d1ffSmrg
408fef5d1ffSmrg        if ((name = Xmalloc(size + 1)) == NULL) {
409fef5d1ffSmrg            status = XvBadAlloc;
410fef5d1ffSmrg            goto out;
411fef5d1ffSmrg        }
412fef5d1ffSmrg        strncpy(name, u.string, size);
413fef5d1ffSmrg        name[size] = '\0';
414fef5d1ffSmrg        pe->name = name;
415fef5d1ffSmrg        pe++;
416fef5d1ffSmrg
417fef5d1ffSmrg        u.buffer += pad_to_int32(size);
418fef5d1ffSmrg    }
419fef5d1ffSmrg
420fef5d1ffSmrg    status = Success;
421fef5d1ffSmrg
422fef5d1ffSmrg  out:
423fef5d1ffSmrg    if (status != Success) {
424fef5d1ffSmrg        XvFreeEncodingInfo(pes);
425fef5d1ffSmrg        pes = NULL;
426fef5d1ffSmrg    }
427fef5d1ffSmrg
428fef5d1ffSmrg    *p_nEncodings = rep.num_encodings;
429fef5d1ffSmrg    *p_pEncodings = pes;
430fef5d1ffSmrg
431fef5d1ffSmrg    Xfree(buffer);
432fef5d1ffSmrg    UnlockDisplay(dpy);
433fef5d1ffSmrg    SyncHandle();
434fef5d1ffSmrg
435fef5d1ffSmrg    return (Success);
4369f606849Smrg}
4379f606849Smrg
4389f606849Smrgvoid
4399f606849SmrgXvFreeEncodingInfo(XvEncodingInfo *pEncodings)
4409f606849Smrg{
441fef5d1ffSmrg    XvEncodingInfo *pe;
442fef5d1ffSmrg    unsigned long ii;
4439f606849Smrg
444fef5d1ffSmrg    if (!pEncodings)
445fef5d1ffSmrg        return;
4469f606849Smrg
447fef5d1ffSmrg    pe = pEncodings;
4489f606849Smrg
449fef5d1ffSmrg    for (ii = 0; ii < pEncodings->num_encodings; ii++, pe++) {
450fef5d1ffSmrg        if (pe->name)
451fef5d1ffSmrg            Xfree(pe->name);
452fef5d1ffSmrg    }
4539f606849Smrg
454fef5d1ffSmrg    Xfree(pEncodings);
4559f606849Smrg}
4569f606849Smrg
4579f606849Smrgint
4589f606849SmrgXvPutVideo(
459fef5d1ffSmrg    Display *dpy,
460fef5d1ffSmrg    XvPortID port,
461fef5d1ffSmrg    Drawable d,
462fef5d1ffSmrg    GC gc,
463fef5d1ffSmrg    int vx, int vy,
464fef5d1ffSmrg    unsigned int vw, unsigned int vh,
465fef5d1ffSmrg    int dx, int dy,
466fef5d1ffSmrg    unsigned int dw, unsigned int dh)
467fef5d1ffSmrg{
468fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
469fef5d1ffSmrg    xvPutVideoReq *req;
470fef5d1ffSmrg
471fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
472fef5d1ffSmrg
473fef5d1ffSmrg    LockDisplay(dpy);
474fef5d1ffSmrg
475fef5d1ffSmrg    FlushGC(dpy, gc);
476fef5d1ffSmrg
477fef5d1ffSmrg    XvGetReq(PutVideo, req);
478fef5d1ffSmrg
479fef5d1ffSmrg    req->port = port;
480fef5d1ffSmrg    req->drawable = d;
481fef5d1ffSmrg    req->gc = gc->gid;
482fef5d1ffSmrg    req->vid_x = vx;
483fef5d1ffSmrg    req->vid_y = vy;
484fef5d1ffSmrg    req->vid_w = vw;
485fef5d1ffSmrg    req->vid_h = vh;
486fef5d1ffSmrg    req->drw_x = dx;
487fef5d1ffSmrg    req->drw_y = dy;
488fef5d1ffSmrg    req->drw_w = dw;
489fef5d1ffSmrg    req->drw_h = dh;
490fef5d1ffSmrg
491fef5d1ffSmrg    UnlockDisplay(dpy);
492fef5d1ffSmrg    SyncHandle();
493fef5d1ffSmrg
494fef5d1ffSmrg    return Success;
4959f606849Smrg}
4969f606849Smrg
4979f606849Smrgint
4989f606849SmrgXvPutStill(
499fef5d1ffSmrg    Display *dpy,
500fef5d1ffSmrg    XvPortID port,
501fef5d1ffSmrg    Drawable d,
502fef5d1ffSmrg    GC gc,
503fef5d1ffSmrg    int vx, int vy,
504fef5d1ffSmrg    unsigned int vw, unsigned int vh,
505fef5d1ffSmrg    int dx, int dy,
506fef5d1ffSmrg    unsigned int dw, unsigned int dh)
507fef5d1ffSmrg{
508fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
509fef5d1ffSmrg    xvPutStillReq *req;
510fef5d1ffSmrg
511fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
512fef5d1ffSmrg
513fef5d1ffSmrg    LockDisplay(dpy);
514fef5d1ffSmrg
515fef5d1ffSmrg    FlushGC(dpy, gc);
516fef5d1ffSmrg
517fef5d1ffSmrg    XvGetReq(PutStill, req);
518fef5d1ffSmrg    req->port = port;
519fef5d1ffSmrg    req->drawable = d;
520fef5d1ffSmrg    req->gc = gc->gid;
521fef5d1ffSmrg    req->vid_x = vx;
522fef5d1ffSmrg    req->vid_y = vy;
523fef5d1ffSmrg    req->vid_w = vw;
524fef5d1ffSmrg    req->vid_h = vh;
525fef5d1ffSmrg    req->drw_x = dx;
526fef5d1ffSmrg    req->drw_y = dy;
527fef5d1ffSmrg    req->drw_w = dw;
528fef5d1ffSmrg    req->drw_h = dh;
529fef5d1ffSmrg
530fef5d1ffSmrg    UnlockDisplay(dpy);
531fef5d1ffSmrg    SyncHandle();
532fef5d1ffSmrg
533fef5d1ffSmrg    return Success;
5349f606849Smrg}
5359f606849Smrg
5369f606849Smrgint
5379f606849SmrgXvGetVideo(
538fef5d1ffSmrg    Display *dpy,
539fef5d1ffSmrg    XvPortID port,
540fef5d1ffSmrg    Drawable d,
541fef5d1ffSmrg    GC gc,
542fef5d1ffSmrg    int vx, int vy,
543fef5d1ffSmrg    unsigned int vw, unsigned int vh,
544fef5d1ffSmrg    int dx, int dy,
545fef5d1ffSmrg    unsigned int dw, unsigned int dh)
546fef5d1ffSmrg{
547fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
548fef5d1ffSmrg    xvGetVideoReq *req;
549fef5d1ffSmrg
550fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
551fef5d1ffSmrg
552fef5d1ffSmrg    LockDisplay(dpy);
553fef5d1ffSmrg
554fef5d1ffSmrg    FlushGC(dpy, gc);
555fef5d1ffSmrg
556fef5d1ffSmrg    XvGetReq(GetVideo, req);
557fef5d1ffSmrg    req->port = port;
558fef5d1ffSmrg    req->drawable = d;
559fef5d1ffSmrg    req->gc = gc->gid;
560fef5d1ffSmrg    req->vid_x = vx;
561fef5d1ffSmrg    req->vid_y = vy;
562fef5d1ffSmrg    req->vid_w = vw;
563fef5d1ffSmrg    req->vid_h = vh;
564fef5d1ffSmrg    req->drw_x = dx;
565fef5d1ffSmrg    req->drw_y = dy;
566fef5d1ffSmrg    req->drw_w = dw;
567fef5d1ffSmrg    req->drw_h = dh;
568fef5d1ffSmrg
569fef5d1ffSmrg    UnlockDisplay(dpy);
570fef5d1ffSmrg    SyncHandle();
571fef5d1ffSmrg
572fef5d1ffSmrg    return Success;
5739f606849Smrg}
5749f606849Smrg
5759f606849Smrgint
5769f606849SmrgXvGetStill(
577fef5d1ffSmrg    Display *dpy,
578fef5d1ffSmrg    XvPortID port,
579fef5d1ffSmrg    Drawable d,
580fef5d1ffSmrg    GC gc,
581fef5d1ffSmrg    int vx, int vy,
582fef5d1ffSmrg    unsigned int vw, unsigned int vh,
583fef5d1ffSmrg    int dx, int dy,
584fef5d1ffSmrg    unsigned int dw, unsigned int dh)
585fef5d1ffSmrg{
586fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
587fef5d1ffSmrg    xvGetStillReq *req;
588fef5d1ffSmrg
589fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
590fef5d1ffSmrg
591fef5d1ffSmrg    LockDisplay(dpy);
592fef5d1ffSmrg
593fef5d1ffSmrg    FlushGC(dpy, gc);
594fef5d1ffSmrg
595fef5d1ffSmrg    XvGetReq(GetStill, req);
596fef5d1ffSmrg    req->port = port;
597fef5d1ffSmrg    req->drawable = d;
598fef5d1ffSmrg    req->gc = gc->gid;
599fef5d1ffSmrg    req->vid_x = vx;
600fef5d1ffSmrg    req->vid_y = vy;
601fef5d1ffSmrg    req->vid_w = vw;
602fef5d1ffSmrg    req->vid_h = vh;
603fef5d1ffSmrg    req->drw_x = dx;
604fef5d1ffSmrg    req->drw_y = dy;
605fef5d1ffSmrg    req->drw_w = dw;
606fef5d1ffSmrg    req->drw_h = dh;
607fef5d1ffSmrg
608fef5d1ffSmrg    UnlockDisplay(dpy);
609fef5d1ffSmrg    SyncHandle();
610fef5d1ffSmrg
611fef5d1ffSmrg    return Success;
6129f606849Smrg}
6139f606849Smrg
6149f606849Smrgint
615fef5d1ffSmrgXvStopVideo(Display *dpy, XvPortID port, Drawable draw)
616fef5d1ffSmrg{
617fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
618fef5d1ffSmrg    xvStopVideoReq *req;
6199f606849Smrg
620fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
6219f606849Smrg
622fef5d1ffSmrg    LockDisplay(dpy);
6239f606849Smrg
624fef5d1ffSmrg    XvGetReq(StopVideo, req);
625fef5d1ffSmrg    req->port = port;
626fef5d1ffSmrg    req->drawable = draw;
6279f606849Smrg
628fef5d1ffSmrg    UnlockDisplay(dpy);
629fef5d1ffSmrg    SyncHandle();
6309f606849Smrg
631fef5d1ffSmrg    return Success;
6329f606849Smrg}
6339f606849Smrg
6349f606849Smrgint
635fef5d1ffSmrgXvGrabPort(Display *dpy, XvPortID port, Time time)
636fef5d1ffSmrg{
637fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
638fef5d1ffSmrg    int result;
639fef5d1ffSmrg    xvGrabPortReply rep;
640fef5d1ffSmrg    xvGrabPortReq *req;
6419f606849Smrg
642fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
6439f606849Smrg
644fef5d1ffSmrg    LockDisplay(dpy);
6459f606849Smrg
646fef5d1ffSmrg    XvGetReq(GrabPort, req);
647fef5d1ffSmrg    req->port = port;
648fef5d1ffSmrg    req->time = time;
6499f606849Smrg
650fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xTrue) == 0)
651fef5d1ffSmrg        rep.result = GrabSuccess;
6529f606849Smrg
653fef5d1ffSmrg    result = rep.result;
6549f606849Smrg
655fef5d1ffSmrg    UnlockDisplay(dpy);
656fef5d1ffSmrg    SyncHandle();
6579f606849Smrg
658fef5d1ffSmrg    return result;
6599f606849Smrg}
6609f606849Smrg
6619f606849Smrgint
662fef5d1ffSmrgXvUngrabPort(Display *dpy, XvPortID port, Time time)
663fef5d1ffSmrg{
664fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
665fef5d1ffSmrg    xvUngrabPortReq *req;
6669f606849Smrg
667fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
6689f606849Smrg
669fef5d1ffSmrg    LockDisplay(dpy);
6709f606849Smrg
671fef5d1ffSmrg    XvGetReq(UngrabPort, req);
672fef5d1ffSmrg    req->port = port;
673fef5d1ffSmrg    req->time = time;
6749f606849Smrg
675fef5d1ffSmrg    UnlockDisplay(dpy);
676fef5d1ffSmrg    SyncHandle();
6779f606849Smrg
678fef5d1ffSmrg    return Success;
6799f606849Smrg}
6809f606849Smrg
6819f606849Smrgint
682fef5d1ffSmrgXvSelectVideoNotify(Display *dpy, Drawable drawable, Bool onoff)
683fef5d1ffSmrg{
684fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
685fef5d1ffSmrg    xvSelectVideoNotifyReq *req;
6869f606849Smrg
687fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
6889f606849Smrg
689fef5d1ffSmrg    LockDisplay(dpy);
6909f606849Smrg
691fef5d1ffSmrg    XvGetReq(SelectVideoNotify, req);
692fef5d1ffSmrg    req->drawable = drawable;
693fef5d1ffSmrg    req->onoff = onoff;
6949f606849Smrg
695fef5d1ffSmrg    UnlockDisplay(dpy);
696fef5d1ffSmrg    SyncHandle();
6979f606849Smrg
698fef5d1ffSmrg    return Success;
6999f606849Smrg}
7009f606849Smrg
7019f606849Smrgint
702fef5d1ffSmrgXvSelectPortNotify(Display *dpy, XvPortID port, Bool onoff)
703fef5d1ffSmrg{
704fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
705fef5d1ffSmrg    xvSelectPortNotifyReq *req;
7069f606849Smrg
707fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
7089f606849Smrg
709fef5d1ffSmrg    LockDisplay(dpy);
7109f606849Smrg
711fef5d1ffSmrg    XvGetReq(SelectPortNotify, req);
712fef5d1ffSmrg    req->port = port;
713fef5d1ffSmrg    req->onoff = onoff;
7149f606849Smrg
715fef5d1ffSmrg    UnlockDisplay(dpy);
716fef5d1ffSmrg    SyncHandle();
7179f606849Smrg
718fef5d1ffSmrg    return Success;
7199f606849Smrg}
7209f606849Smrg
7219f606849Smrgint
722fef5d1ffSmrgXvSetPortAttribute(Display *dpy, XvPortID port, Atom attribute, int value)
7239f606849Smrg{
724fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
725fef5d1ffSmrg    xvSetPortAttributeReq *req;
7269f606849Smrg
727fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
7289f606849Smrg
729fef5d1ffSmrg    LockDisplay(dpy);
7309f606849Smrg
731fef5d1ffSmrg    XvGetReq(SetPortAttribute, req);
732fef5d1ffSmrg    req->port = port;
733fef5d1ffSmrg    req->attribute = attribute;
734fef5d1ffSmrg    req->value = value;
7359f606849Smrg
736fef5d1ffSmrg    UnlockDisplay(dpy);
737fef5d1ffSmrg    SyncHandle();
7389f606849Smrg
739fef5d1ffSmrg    return (Success);
7409f606849Smrg}
7419f606849Smrg
7429f606849Smrgint
743fef5d1ffSmrgXvGetPortAttribute(Display *dpy, XvPortID port, Atom attribute, int *p_value)
7449f606849Smrg{
745fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
746fef5d1ffSmrg    xvGetPortAttributeReq *req;
747fef5d1ffSmrg    xvGetPortAttributeReply rep;
748fef5d1ffSmrg    int status;
7499f606849Smrg
750fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
7519f606849Smrg
752fef5d1ffSmrg    LockDisplay(dpy);
7539f606849Smrg
754fef5d1ffSmrg    XvGetReq(GetPortAttribute, req);
755fef5d1ffSmrg    req->port = port;
756fef5d1ffSmrg    req->attribute = attribute;
7579f606849Smrg
758fef5d1ffSmrg    /* READ THE REPLY */
7599f606849Smrg
760fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) {
761fef5d1ffSmrg        status = XvBadReply;
762fef5d1ffSmrg    }
763fef5d1ffSmrg    else {
764fef5d1ffSmrg        *p_value = rep.value;
765fef5d1ffSmrg        status = Success;
766fef5d1ffSmrg    }
767cdbfa18aSmrg
768fef5d1ffSmrg    UnlockDisplay(dpy);
769fef5d1ffSmrg    SyncHandle();
7709f606849Smrg
771fef5d1ffSmrg    return status;
7729f606849Smrg}
7739f606849Smrg
7749f606849Smrgint
7759f606849SmrgXvQueryBestSize(
776fef5d1ffSmrg    Display *dpy,
777fef5d1ffSmrg    XvPortID port,
778fef5d1ffSmrg    Bool motion,
779fef5d1ffSmrg    unsigned int vid_w,
780fef5d1ffSmrg    unsigned int vid_h,
781fef5d1ffSmrg    unsigned int drw_w,
782fef5d1ffSmrg    unsigned int drw_h,
783fef5d1ffSmrg    unsigned int *p_actual_width,
784fef5d1ffSmrg    unsigned int *p_actual_height)
7859f606849Smrg{
786fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
787fef5d1ffSmrg    xvQueryBestSizeReq *req;
788fef5d1ffSmrg    xvQueryBestSizeReply rep;
789fef5d1ffSmrg    int status;
7909f606849Smrg
791fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
7929f606849Smrg
793fef5d1ffSmrg    LockDisplay(dpy);
7949f606849Smrg
795fef5d1ffSmrg    XvGetReq(QueryBestSize, req);
796fef5d1ffSmrg    req->port = port;
797fef5d1ffSmrg    req->motion = motion;
798fef5d1ffSmrg    req->vid_w = vid_w;
799fef5d1ffSmrg    req->vid_h = vid_h;
800fef5d1ffSmrg    req->drw_w = drw_w;
801fef5d1ffSmrg    req->drw_h = drw_h;
8029f606849Smrg
803fef5d1ffSmrg    /* READ THE REPLY */
8049f606849Smrg
805fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) {
806fef5d1ffSmrg        status = XvBadReply;
807fef5d1ffSmrg    }
808fef5d1ffSmrg    else {
809fef5d1ffSmrg        *p_actual_width = rep.actual_width;
810fef5d1ffSmrg        *p_actual_height = rep.actual_height;
811fef5d1ffSmrg        status = Success;
812fef5d1ffSmrg    }
8139f606849Smrg
814fef5d1ffSmrg    UnlockDisplay(dpy);
815fef5d1ffSmrg    SyncHandle();
8169f606849Smrg
817fef5d1ffSmrg    return status;
8189f606849Smrg}
8199f606849Smrg
8209f606849Smrg
821fef5d1ffSmrgXvAttribute *
8229f606849SmrgXvQueryPortAttributes(Display *dpy, XvPortID port, int *num)
8239f606849Smrg{
824fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
825fef5d1ffSmrg    xvQueryPortAttributesReq *req;
826fef5d1ffSmrg    xvQueryPortAttributesReply rep;
827fef5d1ffSmrg    XvAttribute *ret = NULL;
828fef5d1ffSmrg
829fef5d1ffSmrg    *num = 0;
830fef5d1ffSmrg
831fef5d1ffSmrg    XvCheckExtension(dpy, info, NULL);
832fef5d1ffSmrg
833fef5d1ffSmrg    LockDisplay(dpy);
834fef5d1ffSmrg
835fef5d1ffSmrg    XvGetReq(QueryPortAttributes, req);
836fef5d1ffSmrg    req->port = port;
837fef5d1ffSmrg
838fef5d1ffSmrg    /* READ THE REPLY */
839fef5d1ffSmrg
840fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) {
841fef5d1ffSmrg        goto out;
842fef5d1ffSmrg    }
843fef5d1ffSmrg
844fef5d1ffSmrg    /*
845fef5d1ffSmrg     * X server sends data packed as:
846fef5d1ffSmrg     *   attribute1, name1, attribute2, name2, ...
847fef5d1ffSmrg     * We allocate a single buffer large enough to hold them all and
848fef5d1ffSmrg     * then de-interleave the data so we return it to clients as:
849fef5d1ffSmrg     *   attribute1, attribute2, ..., name1, name2, ...
850fef5d1ffSmrg     * so that clients may refer to attributes as a simple array of
851fef5d1ffSmrg     * structs:  attributes[0], attributes[1], ...
852fef5d1ffSmrg     * and free it as a single/simple buffer.
853fef5d1ffSmrg     */
854fef5d1ffSmrg
855fef5d1ffSmrg    if (rep.num_attributes) {
856fef5d1ffSmrg        unsigned long size;
857fef5d1ffSmrg
858fef5d1ffSmrg        /* limit each part to no more than one half the max size */
859fef5d1ffSmrg        if ((rep.num_attributes < ((INT_MAX / 2) / sizeof(XvAttribute))) &&
860fef5d1ffSmrg            (rep.text_size < (INT_MAX / 2) - 1)) {
861fef5d1ffSmrg            size = (rep.num_attributes * sizeof(XvAttribute)) +
862fef5d1ffSmrg		rep.text_size + 1;
863fef5d1ffSmrg            ret = Xmalloc(size);
864fef5d1ffSmrg        }
865fef5d1ffSmrg
866fef5d1ffSmrg        if (ret != NULL) {
867fef5d1ffSmrg            char *marker = (char *) (&ret[rep.num_attributes]);
868fef5d1ffSmrg            xvAttributeInfo Info;
869fef5d1ffSmrg            unsigned int i;
870fef5d1ffSmrg
871fef5d1ffSmrg            /* keep track of remaining room for text strings */
872fef5d1ffSmrg            size = rep.text_size;
873fef5d1ffSmrg
874fef5d1ffSmrg            for (i = 0; i < rep.num_attributes; i++) {
875fef5d1ffSmrg                _XRead(dpy, (char *) (&Info), sz_xvAttributeInfo);
876fef5d1ffSmrg                ret[i].flags = (int) Info.flags;
877fef5d1ffSmrg                ret[i].min_value = Info.min;
878fef5d1ffSmrg                ret[i].max_value = Info.max;
879fef5d1ffSmrg                ret[i].name = marker;
880fef5d1ffSmrg                if (Info.size <= size) {
881fef5d1ffSmrg                    _XRead(dpy, marker, Info.size);
882fef5d1ffSmrg                    marker += Info.size;
883fef5d1ffSmrg                    size -= Info.size;
884fef5d1ffSmrg                }
885fef5d1ffSmrg                (*num)++;
886fef5d1ffSmrg            }
887fef5d1ffSmrg
888fef5d1ffSmrg            /* ensure final string is nil-terminated to avoid exposure of
889fef5d1ffSmrg               uninitialized memory */
890fef5d1ffSmrg            *marker = '\0';
891fef5d1ffSmrg        }
892fef5d1ffSmrg        else
893fef5d1ffSmrg            _XEatDataWords(dpy, rep.length);
894fef5d1ffSmrg    }
895fef5d1ffSmrg
896fef5d1ffSmrg  out:
897fef5d1ffSmrg    UnlockDisplay(dpy);
898fef5d1ffSmrg    SyncHandle();
899fef5d1ffSmrg
900fef5d1ffSmrg    return ret;
9019f606849Smrg}
9029f606849Smrg
903fef5d1ffSmrgXvImageFormatValues *
904fef5d1ffSmrgXvListImageFormats(Display *dpy, XvPortID port, int *num)
905fef5d1ffSmrg{
906fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
907fef5d1ffSmrg    xvListImageFormatsReq *req;
908fef5d1ffSmrg    xvListImageFormatsReply rep;
909fef5d1ffSmrg    XvImageFormatValues *ret = NULL;
910fef5d1ffSmrg
911fef5d1ffSmrg    *num = 0;
912fef5d1ffSmrg
913fef5d1ffSmrg    XvCheckExtension(dpy, info, NULL);
914fef5d1ffSmrg
915fef5d1ffSmrg    LockDisplay(dpy);
916fef5d1ffSmrg
917fef5d1ffSmrg    XvGetReq(ListImageFormats, req);
918fef5d1ffSmrg    req->port = port;
919fef5d1ffSmrg
920fef5d1ffSmrg    /* READ THE REPLY */
921fef5d1ffSmrg
922fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) {
923fef5d1ffSmrg        goto out;
924fef5d1ffSmrg    }
925fef5d1ffSmrg
926fef5d1ffSmrg    if (rep.num_formats) {
927fef5d1ffSmrg        if (rep.num_formats < (INT_MAX / sizeof(XvImageFormatValues)))
928fef5d1ffSmrg            ret = Xmalloc(rep.num_formats * sizeof(XvImageFormatValues));
929fef5d1ffSmrg
930fef5d1ffSmrg        if (ret != NULL) {
931fef5d1ffSmrg            xvImageFormatInfo Info;
932fef5d1ffSmrg            unsigned int i;
933fef5d1ffSmrg
934fef5d1ffSmrg            for (i = 0; i < rep.num_formats; i++) {
935fef5d1ffSmrg                _XRead(dpy, (char *) (&Info), sz_xvImageFormatInfo);
936fef5d1ffSmrg                ret[i].id = Info.id;
937fef5d1ffSmrg                ret[i].type = Info.type;
938fef5d1ffSmrg                ret[i].byte_order = Info.byte_order;
939fef5d1ffSmrg                memcpy(&(ret[i].guid[0]), &(Info.guid[0]), 16);
940fef5d1ffSmrg                ret[i].bits_per_pixel = Info.bpp;
941fef5d1ffSmrg                ret[i].format = Info.format;
942fef5d1ffSmrg                ret[i].num_planes = Info.num_planes;
943fef5d1ffSmrg                ret[i].depth = Info.depth;
944fef5d1ffSmrg                ret[i].red_mask = Info.red_mask;
945fef5d1ffSmrg                ret[i].green_mask = Info.green_mask;
946fef5d1ffSmrg                ret[i].blue_mask = Info.blue_mask;
947fef5d1ffSmrg                ret[i].y_sample_bits = Info.y_sample_bits;
948fef5d1ffSmrg                ret[i].u_sample_bits = Info.u_sample_bits;
949fef5d1ffSmrg                ret[i].v_sample_bits = Info.v_sample_bits;
950fef5d1ffSmrg                ret[i].horz_y_period = Info.horz_y_period;
951fef5d1ffSmrg                ret[i].horz_u_period = Info.horz_u_period;
952fef5d1ffSmrg                ret[i].horz_v_period = Info.horz_v_period;
953fef5d1ffSmrg                ret[i].vert_y_period = Info.vert_y_period;
954fef5d1ffSmrg                ret[i].vert_u_period = Info.vert_u_period;
955fef5d1ffSmrg                ret[i].vert_v_period = Info.vert_v_period;
956fef5d1ffSmrg                memcpy(&(ret[i].component_order[0]), &(Info.comp_order[0]), 32);
957fef5d1ffSmrg                ret[i].scanline_order = Info.scanline_order;
958fef5d1ffSmrg                (*num)++;
959fef5d1ffSmrg            }
960fef5d1ffSmrg        }
961fef5d1ffSmrg        else
962fef5d1ffSmrg            _XEatDataWords(dpy, rep.length);
963fef5d1ffSmrg    }
964fef5d1ffSmrg
965fef5d1ffSmrg  out:
966fef5d1ffSmrg    UnlockDisplay(dpy);
967fef5d1ffSmrg    SyncHandle();
968fef5d1ffSmrg
969fef5d1ffSmrg    return ret;
9709f606849Smrg}
9719f606849Smrg
972fef5d1ffSmrgXvImage *
973fef5d1ffSmrgXvCreateImage(
974fef5d1ffSmrg    Display *dpy,
975fef5d1ffSmrg    XvPortID port,
976fef5d1ffSmrg    int id,
977fef5d1ffSmrg    char *data,
978fef5d1ffSmrg    int width,
979fef5d1ffSmrg    int height)
980fef5d1ffSmrg{
981fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
982fef5d1ffSmrg    xvQueryImageAttributesReq *req;
983fef5d1ffSmrg    xvQueryImageAttributesReply rep;
984fef5d1ffSmrg    XvImage *ret = NULL;
985fef5d1ffSmrg
986fef5d1ffSmrg    XvCheckExtension(dpy, info, NULL);
987fef5d1ffSmrg
988fef5d1ffSmrg    LockDisplay(dpy);
989fef5d1ffSmrg
990fef5d1ffSmrg    XvGetReq(QueryImageAttributes, req);
991fef5d1ffSmrg    req->id = id;
992fef5d1ffSmrg    req->port = port;
993fef5d1ffSmrg    req->width = width;
994fef5d1ffSmrg    req->height = height;
995fef5d1ffSmrg
996fef5d1ffSmrg    /* READ THE REPLY */
997fef5d1ffSmrg
998fef5d1ffSmrg    if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
999fef5d1ffSmrg        goto out;
1000fef5d1ffSmrg    }
1001fef5d1ffSmrg
1002fef5d1ffSmrg    if (rep.num_planes < ((INT_MAX >> 3) - sizeof(XvImage)))
1003fef5d1ffSmrg        ret = Xmalloc(sizeof(XvImage) + (rep.num_planes << 3));
1004fef5d1ffSmrg
1005fef5d1ffSmrg    if (ret != NULL) {
1006fef5d1ffSmrg        ret->id = id;
1007fef5d1ffSmrg        ret->width = rep.width;
1008fef5d1ffSmrg        ret->height = rep.height;
1009fef5d1ffSmrg        ret->data_size = rep.data_size;
1010fef5d1ffSmrg        ret->num_planes = rep.num_planes;
1011fef5d1ffSmrg        ret->pitches = (int *) (&ret[1]);
1012fef5d1ffSmrg        ret->offsets = ret->pitches + rep.num_planes;
1013fef5d1ffSmrg        ret->data = data;
1014fef5d1ffSmrg        ret->obdata = NULL;
1015fef5d1ffSmrg        _XRead(dpy, (char *) (ret->pitches), rep.num_planes << 2);
1016fef5d1ffSmrg        _XRead(dpy, (char *) (ret->offsets), rep.num_planes << 2);
1017fef5d1ffSmrg    }
1018fef5d1ffSmrg    else
1019fef5d1ffSmrg        _XEatDataWords(dpy, rep.length);
1020fef5d1ffSmrg
1021fef5d1ffSmrg  out:
1022fef5d1ffSmrg    UnlockDisplay(dpy);
1023fef5d1ffSmrg    SyncHandle();
1024fef5d1ffSmrg
1025fef5d1ffSmrg    return ret;
10269f606849Smrg}
10279f606849Smrg
1028fef5d1ffSmrgXvImage *
1029fef5d1ffSmrgXvShmCreateImage(
1030fef5d1ffSmrg    Display *dpy,
1031fef5d1ffSmrg    XvPortID port,
1032fef5d1ffSmrg    int id,
1033fef5d1ffSmrg    char *data,
1034fef5d1ffSmrg    int width,
1035fef5d1ffSmrg    int height,
1036fef5d1ffSmrg    XShmSegmentInfo *shminfo)
1037fef5d1ffSmrg{
1038fef5d1ffSmrg    XvImage *ret;
10399f606849Smrg
1040fef5d1ffSmrg    ret = XvCreateImage(dpy, port, id, data, width, height);
10419f606849Smrg
1042fef5d1ffSmrg    if (ret)
1043fef5d1ffSmrg        ret->obdata = (XPointer) shminfo;
10449f606849Smrg
1045fef5d1ffSmrg    return ret;
10469f606849Smrg}
10479f606849Smrg
1048fef5d1ffSmrgint
1049fef5d1ffSmrgXvPutImage(
1050fef5d1ffSmrg    Display *dpy,
1051fef5d1ffSmrg    XvPortID port,
1052fef5d1ffSmrg    Drawable d,
1053fef5d1ffSmrg    GC gc,
1054fef5d1ffSmrg    XvImage *image,
1055fef5d1ffSmrg    int src_x, int src_y,
1056fef5d1ffSmrg    unsigned int src_w, unsigned int src_h,
1057fef5d1ffSmrg    int dest_x, int dest_y,
1058fef5d1ffSmrg    unsigned int dest_w, unsigned int dest_h)
1059fef5d1ffSmrg{
1060fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
1061fef5d1ffSmrg    xvPutImageReq *req;
1062fef5d1ffSmrg    unsigned int len;
1063fef5d1ffSmrg
1064fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
1065fef5d1ffSmrg
1066fef5d1ffSmrg    LockDisplay(dpy);
1067fef5d1ffSmrg
1068fef5d1ffSmrg    FlushGC(dpy, gc);
1069fef5d1ffSmrg
1070fef5d1ffSmrg    XvGetReq(PutImage, req);
1071fef5d1ffSmrg
1072fef5d1ffSmrg    req->port = port;
1073fef5d1ffSmrg    req->drawable = d;
1074fef5d1ffSmrg    req->gc = gc->gid;
1075fef5d1ffSmrg    req->id = image->id;
1076fef5d1ffSmrg    req->src_x = src_x;
1077fef5d1ffSmrg    req->src_y = src_y;
1078fef5d1ffSmrg    req->src_w = src_w;
1079fef5d1ffSmrg    req->src_h = src_h;
1080fef5d1ffSmrg    req->drw_x = dest_x;
1081fef5d1ffSmrg    req->drw_y = dest_y;
1082fef5d1ffSmrg    req->drw_w = dest_w;
1083fef5d1ffSmrg    req->drw_h = dest_h;
1084fef5d1ffSmrg    req->width = image->width;
1085fef5d1ffSmrg    req->height = image->height;
1086fef5d1ffSmrg
1087fef5d1ffSmrg    len = ((unsigned int) image->data_size + 3) >> 2;
1088fef5d1ffSmrg    SetReqLen(req, len, len);
1089fef5d1ffSmrg
1090fef5d1ffSmrg    /* Yes it's kindof lame that we are sending the whole thing,
1091fef5d1ffSmrg       but for video all of it may be needed even if displaying
1092fef5d1ffSmrg       only a subsection, and I don't want to go through the
1093fef5d1ffSmrg       trouble of creating subregions to send */
1094fef5d1ffSmrg    Data(dpy, (char *) image->data, image->data_size);
1095fef5d1ffSmrg
1096fef5d1ffSmrg    UnlockDisplay(dpy);
1097fef5d1ffSmrg    SyncHandle();
1098fef5d1ffSmrg
1099fef5d1ffSmrg    return Success;
11009f606849Smrg}
11019f606849Smrg
1102fef5d1ffSmrgint
1103fef5d1ffSmrgXvShmPutImage(
1104fef5d1ffSmrg    Display *dpy,
1105fef5d1ffSmrg    XvPortID port,
1106fef5d1ffSmrg    Drawable d,
1107fef5d1ffSmrg    GC gc,
1108fef5d1ffSmrg    XvImage *image,
1109fef5d1ffSmrg    int src_x, int src_y,
1110fef5d1ffSmrg    unsigned int src_w, unsigned int src_h,
1111fef5d1ffSmrg    int dest_x, int dest_y,
1112fef5d1ffSmrg    unsigned int dest_w, unsigned int dest_h,
1113fef5d1ffSmrg    Bool send_event)
1114fef5d1ffSmrg{
1115fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
1116fef5d1ffSmrg    XShmSegmentInfo *shminfo = (XShmSegmentInfo *) image->obdata;
1117fef5d1ffSmrg    xvShmPutImageReq *req;
1118fef5d1ffSmrg
1119fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
1120fef5d1ffSmrg
1121fef5d1ffSmrg    LockDisplay(dpy);
1122fef5d1ffSmrg
1123fef5d1ffSmrg    FlushGC(dpy, gc);
1124fef5d1ffSmrg
1125fef5d1ffSmrg    XvGetReq(ShmPutImage, req);
1126fef5d1ffSmrg
1127fef5d1ffSmrg    req->port = port;
1128fef5d1ffSmrg    req->drawable = d;
1129fef5d1ffSmrg    req->gc = gc->gid;
1130fef5d1ffSmrg    req->shmseg = shminfo->shmseg;
1131fef5d1ffSmrg    req->id = image->id;
1132fef5d1ffSmrg    req->src_x = src_x;
1133fef5d1ffSmrg    req->src_y = src_y;
1134fef5d1ffSmrg    req->src_w = src_w;
1135fef5d1ffSmrg    req->src_h = src_h;
1136fef5d1ffSmrg    req->drw_x = dest_x;
1137fef5d1ffSmrg    req->drw_y = dest_y;
1138fef5d1ffSmrg    req->drw_w = dest_w;
1139fef5d1ffSmrg    req->drw_h = dest_h;
1140fef5d1ffSmrg    req->offset = image->data - shminfo->shmaddr;
1141fef5d1ffSmrg    req->width = image->width;
1142fef5d1ffSmrg    req->height = image->height;
1143fef5d1ffSmrg    req->send_event = send_event;
1144fef5d1ffSmrg
1145fef5d1ffSmrg    UnlockDisplay(dpy);
1146fef5d1ffSmrg    SyncHandle();
1147fef5d1ffSmrg
1148fef5d1ffSmrg    return Success;
11499f606849Smrg}
11509f606849Smrg
11519f606849Smrg
11529f606849Smrgstatic Bool
11539f606849Smrgxv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire)
11549f606849Smrg{
1155fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
1156fef5d1ffSmrg    XvEvent *re = (XvEvent *) host;
1157fef5d1ffSmrg    xvEvent *event = (xvEvent *) wire;
11589f606849Smrg
1159fef5d1ffSmrg    XvCheckExtension(dpy, info, False);
11609f606849Smrg
1161fef5d1ffSmrg    switch ((event->u.u.type & 0x7F) - info->codes->first_event) {
11629f606849Smrg    case XvVideoNotify:
1163fef5d1ffSmrg        re->xvvideo.type = event->u.u.type & 0x7f;
1164fef5d1ffSmrg        re->xvvideo.serial = _XSetLastRequestRead(dpy, (xGenericReply *) event);
1165fef5d1ffSmrg        re->xvvideo.send_event = ((event->u.u.type & 0x80) != 0);
1166fef5d1ffSmrg        re->xvvideo.display = dpy;
1167fef5d1ffSmrg        re->xvvideo.time = event->u.videoNotify.time;
1168fef5d1ffSmrg        re->xvvideo.reason = event->u.videoNotify.reason;
1169fef5d1ffSmrg        re->xvvideo.drawable = event->u.videoNotify.drawable;
1170fef5d1ffSmrg        re->xvvideo.port_id = event->u.videoNotify.port;
1171fef5d1ffSmrg        break;
11729f606849Smrg    case XvPortNotify:
1173fef5d1ffSmrg        re->xvport.type = event->u.u.type & 0x7f;
1174fef5d1ffSmrg        re->xvport.serial = _XSetLastRequestRead(dpy, (xGenericReply *) event);
1175fef5d1ffSmrg        re->xvport.send_event = ((event->u.u.type & 0x80) != 0);
1176fef5d1ffSmrg        re->xvport.display = dpy;
1177fef5d1ffSmrg        re->xvport.time = event->u.portNotify.time;
1178fef5d1ffSmrg        re->xvport.port_id = event->u.portNotify.port;
1179fef5d1ffSmrg        re->xvport.attribute = event->u.portNotify.attribute;
1180fef5d1ffSmrg        re->xvport.value = event->u.portNotify.value;
1181fef5d1ffSmrg        break;
11829f606849Smrg    default:
1183fef5d1ffSmrg        return False;
1184fef5d1ffSmrg    }
11859f606849Smrg
1186fef5d1ffSmrg    return (True);
11879f606849Smrg}
1188