Xv.c revision 949d0342
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;
135949d0342Smrg    *p_requestBase = (unsigned int) info->codes->major_opcode;
136949d0342Smrg    *p_eventBase = (unsigned int) info->codes->first_event;
137949d0342Smrg    *p_errorBase = (unsigned int) 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    XvAdaptorInfo *pas = NULL, *pa;
160fef5d1ffSmrg    XvFormat *pfs, *pf;
161fef5d1ffSmrg    char *buffer = NULL;
162949d0342Smrg    char *end;
163fef5d1ffSmrg    union {
164fef5d1ffSmrg        char *buffer;
165fef5d1ffSmrg        char *string;
166fef5d1ffSmrg        xvAdaptorInfo *pa;
167fef5d1ffSmrg        xvFormat *pf;
1689f606849Smrg    } u;
169fef5d1ffSmrg    int status;
170fef5d1ffSmrg
171fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
172fef5d1ffSmrg
173fef5d1ffSmrg    LockDisplay(dpy);
174fef5d1ffSmrg
175fef5d1ffSmrg    XvGetReq(QueryAdaptors, req);
176949d0342Smrg    req->window = (CARD32) window;
177fef5d1ffSmrg
178fef5d1ffSmrg    /* READ THE REPLY */
179fef5d1ffSmrg
180fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) {
181fef5d1ffSmrg        rep.num_adaptors = 0;
182fef5d1ffSmrg        status = XvBadReply;
183fef5d1ffSmrg        goto out;
184fef5d1ffSmrg    }
185fef5d1ffSmrg
186fef5d1ffSmrg    size = rep.length << 2;
187fef5d1ffSmrg    if (size > 0) {
188fef5d1ffSmrg        if ((buffer = Xmalloc(size)) == NULL) {
189fef5d1ffSmrg            _XEatDataWords(dpy, rep.length);
190fef5d1ffSmrg            status = XvBadAlloc;
191fef5d1ffSmrg            goto out;
192fef5d1ffSmrg        }
193fef5d1ffSmrg        _XRead(dpy, buffer, (long) size);
194fef5d1ffSmrg    }
195fef5d1ffSmrg
196fef5d1ffSmrg    /* GET INPUT ADAPTORS */
197fef5d1ffSmrg
198fef5d1ffSmrg    if (rep.num_adaptors == 0) {
199444fb138Smrg        /* If there are no adaptors, there's nothing more to do. */
200fef5d1ffSmrg        status = Success;
201fef5d1ffSmrg        goto out;
202fef5d1ffSmrg    }
203fef5d1ffSmrg
204444fb138Smrg    u.buffer = buffer;
205444fb138Smrg    end = buffer + size;
206fef5d1ffSmrg
207fef5d1ffSmrg    size = rep.num_adaptors * sizeof(XvAdaptorInfo);
208fef5d1ffSmrg    if ((pas = Xmalloc(size)) == NULL) {
209fef5d1ffSmrg        status = XvBadAlloc;
210fef5d1ffSmrg        goto out;
211fef5d1ffSmrg    }
212fef5d1ffSmrg
213fef5d1ffSmrg    /* INIT ADAPTOR FIELDS */
214fef5d1ffSmrg
215fef5d1ffSmrg    pa = pas;
216949d0342Smrg    for (unsigned int ii = 0; ii < rep.num_adaptors; ii++) {
217fef5d1ffSmrg        pa->num_adaptors = 0;
218fef5d1ffSmrg        pa->name = (char *) NULL;
219fef5d1ffSmrg        pa->formats = (XvFormat *) NULL;
220fef5d1ffSmrg        pa++;
221fef5d1ffSmrg    }
222fef5d1ffSmrg
223fef5d1ffSmrg    pa = pas;
224949d0342Smrg    for (unsigned int ii = 0; ii < rep.num_adaptors; ii++) {
225949d0342Smrg        char *name;
226949d0342Smrg
227444fb138Smrg        if (u.buffer + sz_xvAdaptorInfo > end) {
228444fb138Smrg            status = XvBadReply;
229444fb138Smrg            goto out;
230444fb138Smrg        }
231949d0342Smrg        pa->type = (char) 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
242444fb138Smrg        if (u.buffer + size > end) {
243444fb138Smrg            status = XvBadReply;
244444fb138Smrg            goto out;
245444fb138Smrg        }
246fef5d1ffSmrg        if ((name = Xmalloc(size + 1)) == NULL) {
247fef5d1ffSmrg            status = XvBadAlloc;
248fef5d1ffSmrg            goto out;
249fef5d1ffSmrg        }
250fef5d1ffSmrg        (void) strncpy(name, u.string, size);
251fef5d1ffSmrg        name[size] = '\0';
252fef5d1ffSmrg        pa->name = name;
253fef5d1ffSmrg
254fef5d1ffSmrg        u.buffer += pad_to_int32(size);
255cdbfa18aSmrg
256fef5d1ffSmrg        /* GET FORMATS */
257fef5d1ffSmrg
258fef5d1ffSmrg        size = pa->num_formats * sizeof(XvFormat);
259fef5d1ffSmrg        if ((pfs = Xmalloc(size)) == NULL) {
260fef5d1ffSmrg            status = XvBadAlloc;
261fef5d1ffSmrg            goto out;
262fef5d1ffSmrg        }
263fef5d1ffSmrg
264fef5d1ffSmrg        pf = pfs;
265949d0342Smrg        for (unsigned int jj = 0; jj < pa->num_formats; jj++) {
266444fb138Smrg            if (u.buffer + sz_xvFormat > end) {
267444fb138Smrg                Xfree(pfs);
268444fb138Smrg                status = XvBadReply;
269444fb138Smrg                goto out;
270444fb138Smrg            }
271949d0342Smrg            pf->depth = (char) u.pf->depth;
272fef5d1ffSmrg            pf->visual_id = u.pf->visual;
273fef5d1ffSmrg            pf++;
274fef5d1ffSmrg
275fef5d1ffSmrg            u.buffer += pad_to_int32(sz_xvFormat);
276fef5d1ffSmrg        }
277fef5d1ffSmrg
278fef5d1ffSmrg        pa->formats = pfs;
279fef5d1ffSmrg
280fef5d1ffSmrg        pa++;
281fef5d1ffSmrg
282fef5d1ffSmrg    }
283fef5d1ffSmrg
284fef5d1ffSmrg    status = Success;
285fef5d1ffSmrg
286fef5d1ffSmrg  out:
287fef5d1ffSmrg    if (status != Success) {
288fef5d1ffSmrg        XvFreeAdaptorInfo(pas);
289fef5d1ffSmrg        pas = NULL;
290fef5d1ffSmrg    }
291fef5d1ffSmrg
292fef5d1ffSmrg    *p_nAdaptors = rep.num_adaptors;
293fef5d1ffSmrg    *p_pAdaptors = pas;
294fef5d1ffSmrg
295fef5d1ffSmrg    Xfree(buffer);
296fef5d1ffSmrg    UnlockDisplay(dpy);
297fef5d1ffSmrg    SyncHandle();
298fef5d1ffSmrg
299fef5d1ffSmrg    return status;
3009f606849Smrg}
3019f606849Smrg
3029f606849Smrg
3039f606849Smrgvoid
3049f606849SmrgXvFreeAdaptorInfo(XvAdaptorInfo *pAdaptors)
3059f606849Smrg{
306fef5d1ffSmrg    XvAdaptorInfo *pa;
3079f606849Smrg
308fef5d1ffSmrg    if (!pAdaptors)
309fef5d1ffSmrg        return;
3109f606849Smrg
311fef5d1ffSmrg    pa = pAdaptors;
3129f606849Smrg
313949d0342Smrg    for (unsigned int ii = 0; ii < pAdaptors->num_adaptors; ii++, pa++) {
314fef5d1ffSmrg        if (pa->name) {
315fef5d1ffSmrg            Xfree(pa->name);
316fef5d1ffSmrg        }
317fef5d1ffSmrg        if (pa->formats) {
318fef5d1ffSmrg            Xfree(pa->formats);
319fef5d1ffSmrg        }
320cdbfa18aSmrg    }
3219f606849Smrg
322fef5d1ffSmrg    Xfree(pAdaptors);
3239f606849Smrg}
3249f606849Smrg
3259f606849Smrgint
3269f606849SmrgXvQueryEncodings(
327fef5d1ffSmrg    Display *dpy,
328fef5d1ffSmrg    XvPortID port,
329fef5d1ffSmrg    unsigned int *p_nEncodings,
330fef5d1ffSmrg    XvEncodingInfo ** p_pEncodings)
331fef5d1ffSmrg{
332fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
333fef5d1ffSmrg    xvQueryEncodingsReq *req;
334fef5d1ffSmrg    xvQueryEncodingsReply rep;
335fef5d1ffSmrg    size_t size;
336fef5d1ffSmrg    XvEncodingInfo *pes = NULL, *pe;
337fef5d1ffSmrg    char *buffer = NULL;
338949d0342Smrg    char *end;
339fef5d1ffSmrg    union {
340fef5d1ffSmrg        char *buffer;
341fef5d1ffSmrg        char *string;
342fef5d1ffSmrg        xvEncodingInfo *pe;
3439f606849Smrg    } u;
344fef5d1ffSmrg    int status;
345fef5d1ffSmrg
346fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
347fef5d1ffSmrg
348fef5d1ffSmrg    LockDisplay(dpy);
349fef5d1ffSmrg
350fef5d1ffSmrg    XvGetReq(QueryEncodings, req);
351949d0342Smrg    req->port = (CARD32) port;
352fef5d1ffSmrg
353fef5d1ffSmrg    /* READ THE REPLY */
354fef5d1ffSmrg
355fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) {
356fef5d1ffSmrg        rep.num_encodings = 0;
357fef5d1ffSmrg        status = XvBadReply;
358fef5d1ffSmrg        goto out;
359fef5d1ffSmrg    }
360cdbfa18aSmrg
361fef5d1ffSmrg    size = rep.length << 2;
362fef5d1ffSmrg    if (size > 0) {
363fef5d1ffSmrg        if ((buffer = Xmalloc(size)) == NULL) {
364fef5d1ffSmrg            _XEatDataWords(dpy, rep.length);
365fef5d1ffSmrg            status = XvBadAlloc;
366fef5d1ffSmrg            goto out;
367fef5d1ffSmrg        }
368fef5d1ffSmrg        _XRead(dpy, buffer, (long) size);
369fef5d1ffSmrg    }
370fef5d1ffSmrg
371fef5d1ffSmrg    /* GET ENCODINGS */
372fef5d1ffSmrg
373fef5d1ffSmrg    if (rep.num_encodings == 0) {
374444fb138Smrg        /* If there are no encodings, there's nothing more to do. */
375fef5d1ffSmrg        status = Success;
376fef5d1ffSmrg        goto out;
377fef5d1ffSmrg    }
378fef5d1ffSmrg
379444fb138Smrg    u.buffer = buffer;
380444fb138Smrg    end = buffer + size;
381fef5d1ffSmrg
382fef5d1ffSmrg    size = rep.num_encodings * sizeof(XvEncodingInfo);
383fef5d1ffSmrg    if ((pes = Xmalloc(size)) == NULL) {
384fef5d1ffSmrg        status = XvBadAlloc;
385fef5d1ffSmrg        goto out;
386fef5d1ffSmrg    }
387fef5d1ffSmrg
388fef5d1ffSmrg    /* INITIALIZE THE ENCODING POINTER */
389fef5d1ffSmrg
390fef5d1ffSmrg    pe = pes;
391949d0342Smrg    for (unsigned int jj = 0; jj < rep.num_encodings; jj++) {
392fef5d1ffSmrg        pe->name = (char *) NULL;
393fef5d1ffSmrg        pe->num_encodings = 0;
394fef5d1ffSmrg        pe++;
395fef5d1ffSmrg    }
396fef5d1ffSmrg
397fef5d1ffSmrg    pe = pes;
398949d0342Smrg    for (unsigned int jj = 0; jj < rep.num_encodings; jj++) {
399949d0342Smrg        char *name;
400949d0342Smrg
401444fb138Smrg        if (u.buffer + sz_xvEncodingInfo > end) {
402444fb138Smrg            status = XvBadReply;
403444fb138Smrg            goto out;
404444fb138Smrg        }
405fef5d1ffSmrg        pe->encoding_id = u.pe->encoding;
406fef5d1ffSmrg        pe->width = u.pe->width;
407fef5d1ffSmrg        pe->height = u.pe->height;
408fef5d1ffSmrg        pe->rate.numerator = u.pe->rate.numerator;
409fef5d1ffSmrg        pe->rate.denominator = u.pe->rate.denominator;
410fef5d1ffSmrg        pe->num_encodings = rep.num_encodings - jj;
411fef5d1ffSmrg
412fef5d1ffSmrg        size = u.pe->name_size;
413fef5d1ffSmrg        u.buffer += pad_to_int32(sz_xvEncodingInfo);
414fef5d1ffSmrg
415444fb138Smrg        if (u.buffer + size > end) {
416444fb138Smrg            status = XvBadReply;
417444fb138Smrg            goto out;
418444fb138Smrg        }
419fef5d1ffSmrg        if ((name = Xmalloc(size + 1)) == NULL) {
420fef5d1ffSmrg            status = XvBadAlloc;
421fef5d1ffSmrg            goto out;
422fef5d1ffSmrg        }
423fef5d1ffSmrg        strncpy(name, u.string, size);
424fef5d1ffSmrg        name[size] = '\0';
425fef5d1ffSmrg        pe->name = name;
426fef5d1ffSmrg        pe++;
427fef5d1ffSmrg
428fef5d1ffSmrg        u.buffer += pad_to_int32(size);
429fef5d1ffSmrg    }
430fef5d1ffSmrg
431fef5d1ffSmrg    status = Success;
432fef5d1ffSmrg
433fef5d1ffSmrg  out:
434fef5d1ffSmrg    if (status != Success) {
435fef5d1ffSmrg        XvFreeEncodingInfo(pes);
436fef5d1ffSmrg        pes = NULL;
437fef5d1ffSmrg    }
438fef5d1ffSmrg
439fef5d1ffSmrg    *p_nEncodings = rep.num_encodings;
440fef5d1ffSmrg    *p_pEncodings = pes;
441fef5d1ffSmrg
442fef5d1ffSmrg    Xfree(buffer);
443fef5d1ffSmrg    UnlockDisplay(dpy);
444fef5d1ffSmrg    SyncHandle();
445fef5d1ffSmrg
446fef5d1ffSmrg    return (Success);
4479f606849Smrg}
4489f606849Smrg
4499f606849Smrgvoid
4509f606849SmrgXvFreeEncodingInfo(XvEncodingInfo *pEncodings)
4519f606849Smrg{
452fef5d1ffSmrg    XvEncodingInfo *pe;
4539f606849Smrg
454fef5d1ffSmrg    if (!pEncodings)
455fef5d1ffSmrg        return;
4569f606849Smrg
457fef5d1ffSmrg    pe = pEncodings;
4589f606849Smrg
459949d0342Smrg    for (unsigned long ii = 0; ii < pEncodings->num_encodings; ii++, pe++) {
460fef5d1ffSmrg        if (pe->name)
461fef5d1ffSmrg            Xfree(pe->name);
462fef5d1ffSmrg    }
4639f606849Smrg
464fef5d1ffSmrg    Xfree(pEncodings);
4659f606849Smrg}
4669f606849Smrg
4679f606849Smrgint
4689f606849SmrgXvPutVideo(
469fef5d1ffSmrg    Display *dpy,
470fef5d1ffSmrg    XvPortID port,
471fef5d1ffSmrg    Drawable d,
472fef5d1ffSmrg    GC gc,
473fef5d1ffSmrg    int vx, int vy,
474fef5d1ffSmrg    unsigned int vw, unsigned int vh,
475fef5d1ffSmrg    int dx, int dy,
476fef5d1ffSmrg    unsigned int dw, unsigned int dh)
477fef5d1ffSmrg{
478fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
479fef5d1ffSmrg    xvPutVideoReq *req;
480fef5d1ffSmrg
481fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
482fef5d1ffSmrg
483fef5d1ffSmrg    LockDisplay(dpy);
484fef5d1ffSmrg
485fef5d1ffSmrg    FlushGC(dpy, gc);
486fef5d1ffSmrg
487fef5d1ffSmrg    XvGetReq(PutVideo, req);
488fef5d1ffSmrg
489949d0342Smrg    req->port = (CARD32) port;
490949d0342Smrg    req->drawable = (CARD32) d;
491949d0342Smrg    req->gc = (CARD32) gc->gid;
492949d0342Smrg    req->vid_x = (INT16) vx;
493949d0342Smrg    req->vid_y = (INT16) vy;
494949d0342Smrg    req->vid_w = (CARD16) vw;
495949d0342Smrg    req->vid_h = (CARD16) vh;
496949d0342Smrg    req->drw_x = (INT16) dx;
497949d0342Smrg    req->drw_y = (INT16) dy;
498949d0342Smrg    req->drw_w = (CARD16) dw;
499949d0342Smrg    req->drw_h = (CARD16) dh;
500fef5d1ffSmrg
501fef5d1ffSmrg    UnlockDisplay(dpy);
502fef5d1ffSmrg    SyncHandle();
503fef5d1ffSmrg
504fef5d1ffSmrg    return Success;
5059f606849Smrg}
5069f606849Smrg
5079f606849Smrgint
5089f606849SmrgXvPutStill(
509fef5d1ffSmrg    Display *dpy,
510fef5d1ffSmrg    XvPortID port,
511fef5d1ffSmrg    Drawable d,
512fef5d1ffSmrg    GC gc,
513fef5d1ffSmrg    int vx, int vy,
514fef5d1ffSmrg    unsigned int vw, unsigned int vh,
515fef5d1ffSmrg    int dx, int dy,
516fef5d1ffSmrg    unsigned int dw, unsigned int dh)
517fef5d1ffSmrg{
518fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
519fef5d1ffSmrg    xvPutStillReq *req;
520fef5d1ffSmrg
521fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
522fef5d1ffSmrg
523fef5d1ffSmrg    LockDisplay(dpy);
524fef5d1ffSmrg
525fef5d1ffSmrg    FlushGC(dpy, gc);
526fef5d1ffSmrg
527fef5d1ffSmrg    XvGetReq(PutStill, req);
528949d0342Smrg    req->port = (CARD32) port;
529949d0342Smrg    req->drawable = (CARD32) d;
530949d0342Smrg    req->gc = (CARD32) gc->gid;
531949d0342Smrg    req->vid_x = (INT16) vx;
532949d0342Smrg    req->vid_y = (INT16) vy;
533949d0342Smrg    req->vid_w = (CARD16) vw;
534949d0342Smrg    req->vid_h = (CARD16) vh;
535949d0342Smrg    req->drw_x = (INT16) dx;
536949d0342Smrg    req->drw_y = (INT16) dy;
537949d0342Smrg    req->drw_w = (CARD16) dw;
538949d0342Smrg    req->drw_h = (CARD16) dh;
539fef5d1ffSmrg
540fef5d1ffSmrg    UnlockDisplay(dpy);
541fef5d1ffSmrg    SyncHandle();
542fef5d1ffSmrg
543fef5d1ffSmrg    return Success;
5449f606849Smrg}
5459f606849Smrg
5469f606849Smrgint
5479f606849SmrgXvGetVideo(
548fef5d1ffSmrg    Display *dpy,
549fef5d1ffSmrg    XvPortID port,
550fef5d1ffSmrg    Drawable d,
551fef5d1ffSmrg    GC gc,
552fef5d1ffSmrg    int vx, int vy,
553fef5d1ffSmrg    unsigned int vw, unsigned int vh,
554fef5d1ffSmrg    int dx, int dy,
555fef5d1ffSmrg    unsigned int dw, unsigned int dh)
556fef5d1ffSmrg{
557fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
558fef5d1ffSmrg    xvGetVideoReq *req;
559fef5d1ffSmrg
560fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
561fef5d1ffSmrg
562fef5d1ffSmrg    LockDisplay(dpy);
563fef5d1ffSmrg
564fef5d1ffSmrg    FlushGC(dpy, gc);
565fef5d1ffSmrg
566fef5d1ffSmrg    XvGetReq(GetVideo, req);
567949d0342Smrg    req->port = (CARD32) port;
568949d0342Smrg    req->drawable = (CARD32) d;
569949d0342Smrg    req->gc = (CARD32) gc->gid;
570949d0342Smrg    req->vid_x = (INT16) vx;
571949d0342Smrg    req->vid_y = (INT16) vy;
572949d0342Smrg    req->vid_w = (CARD16) vw;
573949d0342Smrg    req->vid_h = (CARD16) vh;
574949d0342Smrg    req->drw_x = (INT16) dx;
575949d0342Smrg    req->drw_y = (INT16) dy;
576949d0342Smrg    req->drw_w = (CARD16) dw;
577949d0342Smrg    req->drw_h = (CARD16) dh;
578fef5d1ffSmrg
579fef5d1ffSmrg    UnlockDisplay(dpy);
580fef5d1ffSmrg    SyncHandle();
581fef5d1ffSmrg
582fef5d1ffSmrg    return Success;
5839f606849Smrg}
5849f606849Smrg
5859f606849Smrgint
5869f606849SmrgXvGetStill(
587fef5d1ffSmrg    Display *dpy,
588fef5d1ffSmrg    XvPortID port,
589fef5d1ffSmrg    Drawable d,
590fef5d1ffSmrg    GC gc,
591fef5d1ffSmrg    int vx, int vy,
592fef5d1ffSmrg    unsigned int vw, unsigned int vh,
593fef5d1ffSmrg    int dx, int dy,
594fef5d1ffSmrg    unsigned int dw, unsigned int dh)
595fef5d1ffSmrg{
596fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
597fef5d1ffSmrg    xvGetStillReq *req;
598fef5d1ffSmrg
599fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
600fef5d1ffSmrg
601fef5d1ffSmrg    LockDisplay(dpy);
602fef5d1ffSmrg
603fef5d1ffSmrg    FlushGC(dpy, gc);
604fef5d1ffSmrg
605fef5d1ffSmrg    XvGetReq(GetStill, req);
606949d0342Smrg    req->port = (CARD32) port;
607949d0342Smrg    req->drawable = (CARD32) d;
608949d0342Smrg    req->gc = (CARD32) gc->gid;
609949d0342Smrg    req->vid_x = (INT16) vx;
610949d0342Smrg    req->vid_y = (INT16) vy;
611949d0342Smrg    req->vid_w = (CARD16) vw;
612949d0342Smrg    req->vid_h = (CARD16) vh;
613949d0342Smrg    req->drw_x = (INT16) dx;
614949d0342Smrg    req->drw_y = (INT16) dy;
615949d0342Smrg    req->drw_w = (CARD16) dw;
616949d0342Smrg    req->drw_h = (CARD16) dh;
617fef5d1ffSmrg
618fef5d1ffSmrg    UnlockDisplay(dpy);
619fef5d1ffSmrg    SyncHandle();
620fef5d1ffSmrg
621fef5d1ffSmrg    return Success;
6229f606849Smrg}
6239f606849Smrg
6249f606849Smrgint
625fef5d1ffSmrgXvStopVideo(Display *dpy, XvPortID port, Drawable draw)
626fef5d1ffSmrg{
627fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
628fef5d1ffSmrg    xvStopVideoReq *req;
6299f606849Smrg
630fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
6319f606849Smrg
632fef5d1ffSmrg    LockDisplay(dpy);
6339f606849Smrg
634fef5d1ffSmrg    XvGetReq(StopVideo, req);
635949d0342Smrg    req->port = (CARD32) port;
636949d0342Smrg    req->drawable = (CARD32) draw;
6379f606849Smrg
638fef5d1ffSmrg    UnlockDisplay(dpy);
639fef5d1ffSmrg    SyncHandle();
6409f606849Smrg
641fef5d1ffSmrg    return Success;
6429f606849Smrg}
6439f606849Smrg
6449f606849Smrgint
645fef5d1ffSmrgXvGrabPort(Display *dpy, XvPortID port, Time time)
646fef5d1ffSmrg{
647fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
648fef5d1ffSmrg    int result;
649fef5d1ffSmrg    xvGrabPortReply rep;
650fef5d1ffSmrg    xvGrabPortReq *req;
6519f606849Smrg
652fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
6539f606849Smrg
654fef5d1ffSmrg    LockDisplay(dpy);
6559f606849Smrg
656fef5d1ffSmrg    XvGetReq(GrabPort, req);
657949d0342Smrg    req->port = (CARD32) port;
658949d0342Smrg    req->time = (CARD32) time;
6599f606849Smrg
660fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xTrue) == 0)
661fef5d1ffSmrg        rep.result = GrabSuccess;
6629f606849Smrg
663fef5d1ffSmrg    result = rep.result;
6649f606849Smrg
665fef5d1ffSmrg    UnlockDisplay(dpy);
666fef5d1ffSmrg    SyncHandle();
6679f606849Smrg
668fef5d1ffSmrg    return result;
6699f606849Smrg}
6709f606849Smrg
6719f606849Smrgint
672fef5d1ffSmrgXvUngrabPort(Display *dpy, XvPortID port, Time time)
673fef5d1ffSmrg{
674fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
675fef5d1ffSmrg    xvUngrabPortReq *req;
6769f606849Smrg
677fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
6789f606849Smrg
679fef5d1ffSmrg    LockDisplay(dpy);
6809f606849Smrg
681fef5d1ffSmrg    XvGetReq(UngrabPort, req);
682949d0342Smrg    req->port = (CARD32) port;
683949d0342Smrg    req->time = (CARD32) time;
6849f606849Smrg
685fef5d1ffSmrg    UnlockDisplay(dpy);
686fef5d1ffSmrg    SyncHandle();
6879f606849Smrg
688fef5d1ffSmrg    return Success;
6899f606849Smrg}
6909f606849Smrg
6919f606849Smrgint
692fef5d1ffSmrgXvSelectVideoNotify(Display *dpy, Drawable drawable, Bool onoff)
693fef5d1ffSmrg{
694fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
695fef5d1ffSmrg    xvSelectVideoNotifyReq *req;
6969f606849Smrg
697fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
6989f606849Smrg
699fef5d1ffSmrg    LockDisplay(dpy);
7009f606849Smrg
701fef5d1ffSmrg    XvGetReq(SelectVideoNotify, req);
702949d0342Smrg    req->drawable = (CARD32) drawable;
703949d0342Smrg    req->onoff = (BOOL) onoff;
7049f606849Smrg
705fef5d1ffSmrg    UnlockDisplay(dpy);
706fef5d1ffSmrg    SyncHandle();
7079f606849Smrg
708fef5d1ffSmrg    return Success;
7099f606849Smrg}
7109f606849Smrg
7119f606849Smrgint
712fef5d1ffSmrgXvSelectPortNotify(Display *dpy, XvPortID port, Bool onoff)
713fef5d1ffSmrg{
714fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
715fef5d1ffSmrg    xvSelectPortNotifyReq *req;
7169f606849Smrg
717fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
7189f606849Smrg
719fef5d1ffSmrg    LockDisplay(dpy);
7209f606849Smrg
721fef5d1ffSmrg    XvGetReq(SelectPortNotify, req);
722949d0342Smrg    req->port = (CARD32) port;
723949d0342Smrg    req->onoff = (BOOL) onoff;
7249f606849Smrg
725fef5d1ffSmrg    UnlockDisplay(dpy);
726fef5d1ffSmrg    SyncHandle();
7279f606849Smrg
728fef5d1ffSmrg    return Success;
7299f606849Smrg}
7309f606849Smrg
7319f606849Smrgint
732fef5d1ffSmrgXvSetPortAttribute(Display *dpy, XvPortID port, Atom attribute, int value)
7339f606849Smrg{
734fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
735fef5d1ffSmrg    xvSetPortAttributeReq *req;
7369f606849Smrg
737fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
7389f606849Smrg
739fef5d1ffSmrg    LockDisplay(dpy);
7409f606849Smrg
741fef5d1ffSmrg    XvGetReq(SetPortAttribute, req);
742949d0342Smrg    req->port = (CARD32) port;
743949d0342Smrg    req->attribute = (CARD32) attribute;
744fef5d1ffSmrg    req->value = value;
7459f606849Smrg
746fef5d1ffSmrg    UnlockDisplay(dpy);
747fef5d1ffSmrg    SyncHandle();
7489f606849Smrg
749fef5d1ffSmrg    return (Success);
7509f606849Smrg}
7519f606849Smrg
7529f606849Smrgint
753fef5d1ffSmrgXvGetPortAttribute(Display *dpy, XvPortID port, Atom attribute, int *p_value)
7549f606849Smrg{
755fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
756fef5d1ffSmrg    xvGetPortAttributeReq *req;
757fef5d1ffSmrg    xvGetPortAttributeReply rep;
758fef5d1ffSmrg    int status;
7599f606849Smrg
760fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
7619f606849Smrg
762fef5d1ffSmrg    LockDisplay(dpy);
7639f606849Smrg
764fef5d1ffSmrg    XvGetReq(GetPortAttribute, req);
765949d0342Smrg    req->port = (CARD32) port;
766949d0342Smrg    req->attribute = (CARD32) attribute;
7679f606849Smrg
768fef5d1ffSmrg    /* READ THE REPLY */
7699f606849Smrg
770fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) {
771fef5d1ffSmrg        status = XvBadReply;
772fef5d1ffSmrg    }
773fef5d1ffSmrg    else {
774fef5d1ffSmrg        *p_value = rep.value;
775fef5d1ffSmrg        status = Success;
776fef5d1ffSmrg    }
777cdbfa18aSmrg
778fef5d1ffSmrg    UnlockDisplay(dpy);
779fef5d1ffSmrg    SyncHandle();
7809f606849Smrg
781fef5d1ffSmrg    return status;
7829f606849Smrg}
7839f606849Smrg
7849f606849Smrgint
7859f606849SmrgXvQueryBestSize(
786fef5d1ffSmrg    Display *dpy,
787fef5d1ffSmrg    XvPortID port,
788fef5d1ffSmrg    Bool motion,
789fef5d1ffSmrg    unsigned int vid_w,
790fef5d1ffSmrg    unsigned int vid_h,
791fef5d1ffSmrg    unsigned int drw_w,
792fef5d1ffSmrg    unsigned int drw_h,
793fef5d1ffSmrg    unsigned int *p_actual_width,
794fef5d1ffSmrg    unsigned int *p_actual_height)
7959f606849Smrg{
796fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
797fef5d1ffSmrg    xvQueryBestSizeReq *req;
798fef5d1ffSmrg    xvQueryBestSizeReply rep;
799fef5d1ffSmrg    int status;
8009f606849Smrg
801fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
8029f606849Smrg
803fef5d1ffSmrg    LockDisplay(dpy);
8049f606849Smrg
805fef5d1ffSmrg    XvGetReq(QueryBestSize, req);
806949d0342Smrg    req->port = (CARD32) port;
807949d0342Smrg    req->motion = (CARD8) motion;
808949d0342Smrg    req->vid_w = (CARD16) vid_w;
809949d0342Smrg    req->vid_h = (CARD16) vid_h;
810949d0342Smrg    req->drw_w = (CARD16) drw_w;
811949d0342Smrg    req->drw_h = (CARD16) drw_h;
8129f606849Smrg
813fef5d1ffSmrg    /* READ THE REPLY */
8149f606849Smrg
815fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) {
816fef5d1ffSmrg        status = XvBadReply;
817fef5d1ffSmrg    }
818fef5d1ffSmrg    else {
819fef5d1ffSmrg        *p_actual_width = rep.actual_width;
820fef5d1ffSmrg        *p_actual_height = rep.actual_height;
821fef5d1ffSmrg        status = Success;
822fef5d1ffSmrg    }
8239f606849Smrg
824fef5d1ffSmrg    UnlockDisplay(dpy);
825fef5d1ffSmrg    SyncHandle();
8269f606849Smrg
827fef5d1ffSmrg    return status;
8289f606849Smrg}
8299f606849Smrg
8309f606849Smrg
831fef5d1ffSmrgXvAttribute *
8329f606849SmrgXvQueryPortAttributes(Display *dpy, XvPortID port, int *num)
8339f606849Smrg{
834fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
835fef5d1ffSmrg    xvQueryPortAttributesReq *req;
836fef5d1ffSmrg    xvQueryPortAttributesReply rep;
837fef5d1ffSmrg    XvAttribute *ret = NULL;
838fef5d1ffSmrg
839fef5d1ffSmrg    *num = 0;
840fef5d1ffSmrg
841fef5d1ffSmrg    XvCheckExtension(dpy, info, NULL);
842fef5d1ffSmrg
843fef5d1ffSmrg    LockDisplay(dpy);
844fef5d1ffSmrg
845fef5d1ffSmrg    XvGetReq(QueryPortAttributes, req);
846949d0342Smrg    req->port = (CARD32) port;
847fef5d1ffSmrg
848fef5d1ffSmrg    /* READ THE REPLY */
849fef5d1ffSmrg
850fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) {
851fef5d1ffSmrg        goto out;
852fef5d1ffSmrg    }
853fef5d1ffSmrg
854fef5d1ffSmrg    /*
855fef5d1ffSmrg     * X server sends data packed as:
856fef5d1ffSmrg     *   attribute1, name1, attribute2, name2, ...
857fef5d1ffSmrg     * We allocate a single buffer large enough to hold them all and
858fef5d1ffSmrg     * then de-interleave the data so we return it to clients as:
859fef5d1ffSmrg     *   attribute1, attribute2, ..., name1, name2, ...
860fef5d1ffSmrg     * so that clients may refer to attributes as a simple array of
861fef5d1ffSmrg     * structs:  attributes[0], attributes[1], ...
862fef5d1ffSmrg     * and free it as a single/simple buffer.
863fef5d1ffSmrg     */
864fef5d1ffSmrg
865fef5d1ffSmrg    if (rep.num_attributes) {
866fef5d1ffSmrg        /* limit each part to no more than one half the max size */
867fef5d1ffSmrg        if ((rep.num_attributes < ((INT_MAX / 2) / sizeof(XvAttribute))) &&
868fef5d1ffSmrg            (rep.text_size < (INT_MAX / 2) - 1)) {
869949d0342Smrg            unsigned long size;
870949d0342Smrg
871fef5d1ffSmrg            size = (rep.num_attributes * sizeof(XvAttribute)) +
872fef5d1ffSmrg		rep.text_size + 1;
873fef5d1ffSmrg            ret = Xmalloc(size);
874fef5d1ffSmrg        }
875fef5d1ffSmrg
876fef5d1ffSmrg        if (ret != NULL) {
877fef5d1ffSmrg            char *marker = (char *) (&ret[rep.num_attributes]);
878fef5d1ffSmrg            xvAttributeInfo Info;
879fef5d1ffSmrg
880fef5d1ffSmrg            /* keep track of remaining room for text strings */
881949d0342Smrg            unsigned long size = rep.text_size;
882fef5d1ffSmrg
883949d0342Smrg            for (unsigned int i = 0; i < rep.num_attributes; i++) {
884fef5d1ffSmrg                _XRead(dpy, (char *) (&Info), sz_xvAttributeInfo);
885fef5d1ffSmrg                ret[i].flags = (int) Info.flags;
886fef5d1ffSmrg                ret[i].min_value = Info.min;
887fef5d1ffSmrg                ret[i].max_value = Info.max;
888fef5d1ffSmrg                ret[i].name = marker;
889fef5d1ffSmrg                if (Info.size <= size) {
890fef5d1ffSmrg                    _XRead(dpy, marker, Info.size);
891fef5d1ffSmrg                    marker += Info.size;
892fef5d1ffSmrg                    size -= Info.size;
893fef5d1ffSmrg                }
894fef5d1ffSmrg                (*num)++;
895fef5d1ffSmrg            }
896fef5d1ffSmrg
897fef5d1ffSmrg            /* ensure final string is nil-terminated to avoid exposure of
898fef5d1ffSmrg               uninitialized memory */
899fef5d1ffSmrg            *marker = '\0';
900fef5d1ffSmrg        }
901fef5d1ffSmrg        else
902fef5d1ffSmrg            _XEatDataWords(dpy, rep.length);
903fef5d1ffSmrg    }
904fef5d1ffSmrg
905fef5d1ffSmrg  out:
906fef5d1ffSmrg    UnlockDisplay(dpy);
907fef5d1ffSmrg    SyncHandle();
908fef5d1ffSmrg
909fef5d1ffSmrg    return ret;
9109f606849Smrg}
9119f606849Smrg
912fef5d1ffSmrgXvImageFormatValues *
913fef5d1ffSmrgXvListImageFormats(Display *dpy, XvPortID port, int *num)
914fef5d1ffSmrg{
915fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
916fef5d1ffSmrg    xvListImageFormatsReq *req;
917fef5d1ffSmrg    xvListImageFormatsReply rep;
918fef5d1ffSmrg    XvImageFormatValues *ret = NULL;
919fef5d1ffSmrg
920fef5d1ffSmrg    *num = 0;
921fef5d1ffSmrg
922fef5d1ffSmrg    XvCheckExtension(dpy, info, NULL);
923fef5d1ffSmrg
924fef5d1ffSmrg    LockDisplay(dpy);
925fef5d1ffSmrg
926fef5d1ffSmrg    XvGetReq(ListImageFormats, req);
927949d0342Smrg    req->port = (CARD32) port;
928fef5d1ffSmrg
929fef5d1ffSmrg    /* READ THE REPLY */
930fef5d1ffSmrg
931fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) {
932fef5d1ffSmrg        goto out;
933fef5d1ffSmrg    }
934fef5d1ffSmrg
935fef5d1ffSmrg    if (rep.num_formats) {
936fef5d1ffSmrg        if (rep.num_formats < (INT_MAX / sizeof(XvImageFormatValues)))
937fef5d1ffSmrg            ret = Xmalloc(rep.num_formats * sizeof(XvImageFormatValues));
938fef5d1ffSmrg
939fef5d1ffSmrg        if (ret != NULL) {
940949d0342Smrg            for (unsigned int i = 0; i < rep.num_formats; i++) {
941949d0342Smrg                xvImageFormatInfo Info;
942fef5d1ffSmrg
943fef5d1ffSmrg                _XRead(dpy, (char *) (&Info), sz_xvImageFormatInfo);
944949d0342Smrg                ret[i].id = (int) Info.id;
945fef5d1ffSmrg                ret[i].type = Info.type;
946fef5d1ffSmrg                ret[i].byte_order = Info.byte_order;
947fef5d1ffSmrg                memcpy(&(ret[i].guid[0]), &(Info.guid[0]), 16);
948fef5d1ffSmrg                ret[i].bits_per_pixel = Info.bpp;
949fef5d1ffSmrg                ret[i].format = Info.format;
950fef5d1ffSmrg                ret[i].num_planes = Info.num_planes;
951fef5d1ffSmrg                ret[i].depth = Info.depth;
952fef5d1ffSmrg                ret[i].red_mask = Info.red_mask;
953fef5d1ffSmrg                ret[i].green_mask = Info.green_mask;
954fef5d1ffSmrg                ret[i].blue_mask = Info.blue_mask;
955fef5d1ffSmrg                ret[i].y_sample_bits = Info.y_sample_bits;
956fef5d1ffSmrg                ret[i].u_sample_bits = Info.u_sample_bits;
957fef5d1ffSmrg                ret[i].v_sample_bits = Info.v_sample_bits;
958fef5d1ffSmrg                ret[i].horz_y_period = Info.horz_y_period;
959fef5d1ffSmrg                ret[i].horz_u_period = Info.horz_u_period;
960fef5d1ffSmrg                ret[i].horz_v_period = Info.horz_v_period;
961fef5d1ffSmrg                ret[i].vert_y_period = Info.vert_y_period;
962fef5d1ffSmrg                ret[i].vert_u_period = Info.vert_u_period;
963fef5d1ffSmrg                ret[i].vert_v_period = Info.vert_v_period;
964fef5d1ffSmrg                memcpy(&(ret[i].component_order[0]), &(Info.comp_order[0]), 32);
965fef5d1ffSmrg                ret[i].scanline_order = Info.scanline_order;
966fef5d1ffSmrg                (*num)++;
967fef5d1ffSmrg            }
968fef5d1ffSmrg        }
969fef5d1ffSmrg        else
970fef5d1ffSmrg            _XEatDataWords(dpy, rep.length);
971fef5d1ffSmrg    }
972fef5d1ffSmrg
973fef5d1ffSmrg  out:
974fef5d1ffSmrg    UnlockDisplay(dpy);
975fef5d1ffSmrg    SyncHandle();
976fef5d1ffSmrg
977fef5d1ffSmrg    return ret;
9789f606849Smrg}
9799f606849Smrg
980fef5d1ffSmrgXvImage *
981fef5d1ffSmrgXvCreateImage(
982fef5d1ffSmrg    Display *dpy,
983fef5d1ffSmrg    XvPortID port,
984fef5d1ffSmrg    int id,
985fef5d1ffSmrg    char *data,
986fef5d1ffSmrg    int width,
987fef5d1ffSmrg    int height)
988fef5d1ffSmrg{
989fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
990fef5d1ffSmrg    xvQueryImageAttributesReq *req;
991fef5d1ffSmrg    xvQueryImageAttributesReply rep;
992fef5d1ffSmrg    XvImage *ret = NULL;
993fef5d1ffSmrg
994fef5d1ffSmrg    XvCheckExtension(dpy, info, NULL);
995fef5d1ffSmrg
996fef5d1ffSmrg    LockDisplay(dpy);
997fef5d1ffSmrg
998fef5d1ffSmrg    XvGetReq(QueryImageAttributes, req);
999949d0342Smrg    req->id = (CARD32) id;
1000949d0342Smrg    req->port = (CARD32) port;
1001949d0342Smrg    req->width = (CARD16) width;
1002949d0342Smrg    req->height = (CARD16) height;
1003fef5d1ffSmrg
1004fef5d1ffSmrg    /* READ THE REPLY */
1005fef5d1ffSmrg
1006fef5d1ffSmrg    if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
1007fef5d1ffSmrg        goto out;
1008fef5d1ffSmrg    }
1009fef5d1ffSmrg
1010fef5d1ffSmrg    if (rep.num_planes < ((INT_MAX >> 3) - sizeof(XvImage)))
1011fef5d1ffSmrg        ret = Xmalloc(sizeof(XvImage) + (rep.num_planes << 3));
1012fef5d1ffSmrg
1013fef5d1ffSmrg    if (ret != NULL) {
1014fef5d1ffSmrg        ret->id = id;
1015fef5d1ffSmrg        ret->width = rep.width;
1016fef5d1ffSmrg        ret->height = rep.height;
1017949d0342Smrg        ret->data_size = (int) rep.data_size;
1018949d0342Smrg        ret->num_planes = (int) rep.num_planes;
1019fef5d1ffSmrg        ret->pitches = (int *) (&ret[1]);
1020fef5d1ffSmrg        ret->offsets = ret->pitches + rep.num_planes;
1021fef5d1ffSmrg        ret->data = data;
1022fef5d1ffSmrg        ret->obdata = NULL;
1023fef5d1ffSmrg        _XRead(dpy, (char *) (ret->pitches), rep.num_planes << 2);
1024fef5d1ffSmrg        _XRead(dpy, (char *) (ret->offsets), rep.num_planes << 2);
1025fef5d1ffSmrg    }
1026fef5d1ffSmrg    else
1027fef5d1ffSmrg        _XEatDataWords(dpy, rep.length);
1028fef5d1ffSmrg
1029fef5d1ffSmrg  out:
1030fef5d1ffSmrg    UnlockDisplay(dpy);
1031fef5d1ffSmrg    SyncHandle();
1032fef5d1ffSmrg
1033fef5d1ffSmrg    return ret;
10349f606849Smrg}
10359f606849Smrg
1036fef5d1ffSmrgXvImage *
1037fef5d1ffSmrgXvShmCreateImage(
1038fef5d1ffSmrg    Display *dpy,
1039fef5d1ffSmrg    XvPortID port,
1040fef5d1ffSmrg    int id,
1041fef5d1ffSmrg    char *data,
1042fef5d1ffSmrg    int width,
1043fef5d1ffSmrg    int height,
1044fef5d1ffSmrg    XShmSegmentInfo *shminfo)
1045fef5d1ffSmrg{
1046fef5d1ffSmrg    XvImage *ret;
10479f606849Smrg
1048fef5d1ffSmrg    ret = XvCreateImage(dpy, port, id, data, width, height);
10499f606849Smrg
1050fef5d1ffSmrg    if (ret)
1051fef5d1ffSmrg        ret->obdata = (XPointer) shminfo;
10529f606849Smrg
1053fef5d1ffSmrg    return ret;
10549f606849Smrg}
10559f606849Smrg
1056fef5d1ffSmrgint
1057fef5d1ffSmrgXvPutImage(
1058fef5d1ffSmrg    Display *dpy,
1059fef5d1ffSmrg    XvPortID port,
1060fef5d1ffSmrg    Drawable d,
1061fef5d1ffSmrg    GC gc,
1062fef5d1ffSmrg    XvImage *image,
1063fef5d1ffSmrg    int src_x, int src_y,
1064fef5d1ffSmrg    unsigned int src_w, unsigned int src_h,
1065fef5d1ffSmrg    int dest_x, int dest_y,
1066fef5d1ffSmrg    unsigned int dest_w, unsigned int dest_h)
1067fef5d1ffSmrg{
1068fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
1069fef5d1ffSmrg    xvPutImageReq *req;
1070fef5d1ffSmrg    unsigned int len;
1071fef5d1ffSmrg
1072fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
1073fef5d1ffSmrg
1074fef5d1ffSmrg    LockDisplay(dpy);
1075fef5d1ffSmrg
1076fef5d1ffSmrg    FlushGC(dpy, gc);
1077fef5d1ffSmrg
1078fef5d1ffSmrg    XvGetReq(PutImage, req);
1079fef5d1ffSmrg
1080949d0342Smrg    req->port = (CARD32) port;
1081949d0342Smrg    req->drawable = (CARD32) d;
1082949d0342Smrg    req->gc = (CARD32) gc->gid;
1083949d0342Smrg    req->id = (CARD32) image->id;
1084949d0342Smrg    req->src_x = (INT16) src_x;
1085949d0342Smrg    req->src_y = (INT16) src_y;
1086949d0342Smrg    req->src_w = (CARD16) src_w;
1087949d0342Smrg    req->src_h = (CARD16) src_h;
1088949d0342Smrg    req->drw_x = (INT16) dest_x;
1089949d0342Smrg    req->drw_y = (INT16) dest_y;
1090949d0342Smrg    req->drw_w = (CARD16) dest_w;
1091949d0342Smrg    req->drw_h = (CARD16) dest_h;
1092949d0342Smrg    req->width = (CARD16) image->width;
1093949d0342Smrg    req->height = (CARD16) image->height;
1094fef5d1ffSmrg
1095fef5d1ffSmrg    len = ((unsigned int) image->data_size + 3) >> 2;
1096fef5d1ffSmrg    SetReqLen(req, len, len);
1097fef5d1ffSmrg
1098fef5d1ffSmrg    /* Yes it's kindof lame that we are sending the whole thing,
1099fef5d1ffSmrg       but for video all of it may be needed even if displaying
1100fef5d1ffSmrg       only a subsection, and I don't want to go through the
1101fef5d1ffSmrg       trouble of creating subregions to send */
1102fef5d1ffSmrg    Data(dpy, (char *) image->data, image->data_size);
1103fef5d1ffSmrg
1104fef5d1ffSmrg    UnlockDisplay(dpy);
1105fef5d1ffSmrg    SyncHandle();
1106fef5d1ffSmrg
1107fef5d1ffSmrg    return Success;
11089f606849Smrg}
11099f606849Smrg
1110fef5d1ffSmrgint
1111fef5d1ffSmrgXvShmPutImage(
1112fef5d1ffSmrg    Display *dpy,
1113fef5d1ffSmrg    XvPortID port,
1114fef5d1ffSmrg    Drawable d,
1115fef5d1ffSmrg    GC gc,
1116fef5d1ffSmrg    XvImage *image,
1117fef5d1ffSmrg    int src_x, int src_y,
1118fef5d1ffSmrg    unsigned int src_w, unsigned int src_h,
1119fef5d1ffSmrg    int dest_x, int dest_y,
1120fef5d1ffSmrg    unsigned int dest_w, unsigned int dest_h,
1121fef5d1ffSmrg    Bool send_event)
1122fef5d1ffSmrg{
1123fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
1124fef5d1ffSmrg    XShmSegmentInfo *shminfo = (XShmSegmentInfo *) image->obdata;
1125fef5d1ffSmrg    xvShmPutImageReq *req;
1126fef5d1ffSmrg
1127fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
1128fef5d1ffSmrg
1129fef5d1ffSmrg    LockDisplay(dpy);
1130fef5d1ffSmrg
1131fef5d1ffSmrg    FlushGC(dpy, gc);
1132fef5d1ffSmrg
1133fef5d1ffSmrg    XvGetReq(ShmPutImage, req);
1134fef5d1ffSmrg
1135949d0342Smrg    req->port = (CARD32) port;
1136949d0342Smrg    req->drawable = (CARD32) d;
1137949d0342Smrg    req->gc = (CARD32) gc->gid;
1138949d0342Smrg    req->shmseg = (CARD32) shminfo->shmseg;
1139949d0342Smrg    req->id = (CARD32) image->id;
1140949d0342Smrg    req->src_x = (INT16) src_x;
1141949d0342Smrg    req->src_y = (INT16) src_y;
1142949d0342Smrg    req->src_w = (CARD16) src_w;
1143949d0342Smrg    req->src_h = (CARD16) src_h;
1144949d0342Smrg    req->drw_x = (INT16) dest_x;
1145949d0342Smrg    req->drw_y = (INT16) dest_y;
1146949d0342Smrg    req->drw_w = (CARD16) dest_w;
1147949d0342Smrg    req->drw_h = (CARD16) dest_h;
1148949d0342Smrg    req->offset = (CARD32) (image->data - shminfo->shmaddr);
1149949d0342Smrg    req->width = (CARD16) image->width;
1150949d0342Smrg    req->height = (CARD16) image->height;
1151949d0342Smrg    req->send_event = (CARD8) send_event;
1152fef5d1ffSmrg
1153fef5d1ffSmrg    UnlockDisplay(dpy);
1154fef5d1ffSmrg    SyncHandle();
1155fef5d1ffSmrg
1156fef5d1ffSmrg    return Success;
11579f606849Smrg}
11589f606849Smrg
11599f606849Smrg
11609f606849Smrgstatic Bool
11619f606849Smrgxv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire)
11629f606849Smrg{
1163fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
1164fef5d1ffSmrg    XvEvent *re = (XvEvent *) host;
1165fef5d1ffSmrg    xvEvent *event = (xvEvent *) wire;
11669f606849Smrg
1167fef5d1ffSmrg    XvCheckExtension(dpy, info, False);
11689f606849Smrg
1169fef5d1ffSmrg    switch ((event->u.u.type & 0x7F) - info->codes->first_event) {
11709f606849Smrg    case XvVideoNotify:
1171fef5d1ffSmrg        re->xvvideo.type = event->u.u.type & 0x7f;
1172fef5d1ffSmrg        re->xvvideo.serial = _XSetLastRequestRead(dpy, (xGenericReply *) event);
1173fef5d1ffSmrg        re->xvvideo.send_event = ((event->u.u.type & 0x80) != 0);
1174fef5d1ffSmrg        re->xvvideo.display = dpy;
1175fef5d1ffSmrg        re->xvvideo.time = event->u.videoNotify.time;
1176fef5d1ffSmrg        re->xvvideo.reason = event->u.videoNotify.reason;
1177fef5d1ffSmrg        re->xvvideo.drawable = event->u.videoNotify.drawable;
1178fef5d1ffSmrg        re->xvvideo.port_id = event->u.videoNotify.port;
1179fef5d1ffSmrg        break;
11809f606849Smrg    case XvPortNotify:
1181fef5d1ffSmrg        re->xvport.type = event->u.u.type & 0x7f;
1182fef5d1ffSmrg        re->xvport.serial = _XSetLastRequestRead(dpy, (xGenericReply *) event);
1183fef5d1ffSmrg        re->xvport.send_event = ((event->u.u.type & 0x80) != 0);
1184fef5d1ffSmrg        re->xvport.display = dpy;
1185fef5d1ffSmrg        re->xvport.time = event->u.portNotify.time;
1186fef5d1ffSmrg        re->xvport.port_id = event->u.portNotify.port;
1187fef5d1ffSmrg        re->xvport.attribute = event->u.portNotify.attribute;
1188fef5d1ffSmrg        re->xvport.value = event->u.portNotify.value;
1189fef5d1ffSmrg        break;
11909f606849Smrg    default:
1191fef5d1ffSmrg        return False;
1192fef5d1ffSmrg    }
11939f606849Smrg
1194fef5d1ffSmrg    return (True);
11959f606849Smrg}
1196