Xv.c revision 444fb138
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;
161444fb138Smrg    char *end;
162fef5d1ffSmrg    XvAdaptorInfo *pas = NULL, *pa;
163fef5d1ffSmrg    XvFormat *pfs, *pf;
164fef5d1ffSmrg    char *buffer = NULL;
165fef5d1ffSmrg    union {
166fef5d1ffSmrg        char *buffer;
167fef5d1ffSmrg        char *string;
168fef5d1ffSmrg        xvAdaptorInfo *pa;
169fef5d1ffSmrg        xvFormat *pf;
1709f606849Smrg    } u;
171fef5d1ffSmrg    int status;
172fef5d1ffSmrg
173fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
174fef5d1ffSmrg
175fef5d1ffSmrg    LockDisplay(dpy);
176fef5d1ffSmrg
177fef5d1ffSmrg    XvGetReq(QueryAdaptors, req);
178fef5d1ffSmrg    req->window = window;
179fef5d1ffSmrg
180fef5d1ffSmrg    /* READ THE REPLY */
181fef5d1ffSmrg
182fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) {
183fef5d1ffSmrg        rep.num_adaptors = 0;
184fef5d1ffSmrg        status = XvBadReply;
185fef5d1ffSmrg        goto out;
186fef5d1ffSmrg    }
187fef5d1ffSmrg
188fef5d1ffSmrg    size = rep.length << 2;
189fef5d1ffSmrg    if (size > 0) {
190fef5d1ffSmrg        if ((buffer = Xmalloc(size)) == NULL) {
191fef5d1ffSmrg            _XEatDataWords(dpy, rep.length);
192fef5d1ffSmrg            status = XvBadAlloc;
193fef5d1ffSmrg            goto out;
194fef5d1ffSmrg        }
195fef5d1ffSmrg        _XRead(dpy, buffer, (long) size);
196fef5d1ffSmrg    }
197fef5d1ffSmrg
198fef5d1ffSmrg    /* GET INPUT ADAPTORS */
199fef5d1ffSmrg
200fef5d1ffSmrg    if (rep.num_adaptors == 0) {
201444fb138Smrg        /* If there are no adaptors, there's nothing more to do. */
202fef5d1ffSmrg        status = Success;
203fef5d1ffSmrg        goto out;
204fef5d1ffSmrg    }
205fef5d1ffSmrg
206444fb138Smrg    u.buffer = buffer;
207444fb138Smrg    end = buffer + size;
208fef5d1ffSmrg
209fef5d1ffSmrg    size = rep.num_adaptors * sizeof(XvAdaptorInfo);
210fef5d1ffSmrg    if ((pas = Xmalloc(size)) == NULL) {
211fef5d1ffSmrg        status = XvBadAlloc;
212fef5d1ffSmrg        goto out;
213fef5d1ffSmrg    }
214fef5d1ffSmrg
215fef5d1ffSmrg    /* INIT ADAPTOR FIELDS */
216fef5d1ffSmrg
217fef5d1ffSmrg    pa = pas;
218fef5d1ffSmrg    for (ii = 0; ii < rep.num_adaptors; ii++) {
219fef5d1ffSmrg        pa->num_adaptors = 0;
220fef5d1ffSmrg        pa->name = (char *) NULL;
221fef5d1ffSmrg        pa->formats = (XvFormat *) NULL;
222fef5d1ffSmrg        pa++;
223fef5d1ffSmrg    }
224fef5d1ffSmrg
225fef5d1ffSmrg    pa = pas;
226fef5d1ffSmrg    for (ii = 0; ii < rep.num_adaptors; ii++) {
227444fb138Smrg        if (u.buffer + sz_xvAdaptorInfo > end) {
228444fb138Smrg            status = XvBadReply;
229444fb138Smrg            goto out;
230444fb138Smrg        }
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
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;
265fef5d1ffSmrg        for (jj = 0; jj < pa->num_formats; jj++) {
266444fb138Smrg            if (u.buffer + sz_xvFormat > end) {
267444fb138Smrg                Xfree(pfs);
268444fb138Smrg                status = XvBadReply;
269444fb138Smrg                goto out;
270444fb138Smrg            }
271fef5d1ffSmrg            pf->depth = 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;
307fef5d1ffSmrg    unsigned int ii;
3089f606849Smrg
309fef5d1ffSmrg    if (!pAdaptors)
310fef5d1ffSmrg        return;
3119f606849Smrg
312fef5d1ffSmrg    pa = pAdaptors;
3139f606849Smrg
314fef5d1ffSmrg    for (ii = 0; ii < pAdaptors->num_adaptors; ii++, pa++) {
315fef5d1ffSmrg        if (pa->name) {
316fef5d1ffSmrg            Xfree(pa->name);
317fef5d1ffSmrg        }
318fef5d1ffSmrg        if (pa->formats) {
319fef5d1ffSmrg            Xfree(pa->formats);
320fef5d1ffSmrg        }
321cdbfa18aSmrg    }
3229f606849Smrg
323fef5d1ffSmrg    Xfree(pAdaptors);
3249f606849Smrg}
3259f606849Smrg
3269f606849Smrgint
3279f606849SmrgXvQueryEncodings(
328fef5d1ffSmrg    Display *dpy,
329fef5d1ffSmrg    XvPortID port,
330fef5d1ffSmrg    unsigned int *p_nEncodings,
331fef5d1ffSmrg    XvEncodingInfo ** p_pEncodings)
332fef5d1ffSmrg{
333fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
334fef5d1ffSmrg    xvQueryEncodingsReq *req;
335fef5d1ffSmrg    xvQueryEncodingsReply rep;
336fef5d1ffSmrg    size_t size;
337fef5d1ffSmrg    unsigned int jj;
338fef5d1ffSmrg    char *name;
339444fb138Smrg    char *end;
340fef5d1ffSmrg    XvEncodingInfo *pes = NULL, *pe;
341fef5d1ffSmrg    char *buffer = NULL;
342fef5d1ffSmrg    union {
343fef5d1ffSmrg        char *buffer;
344fef5d1ffSmrg        char *string;
345fef5d1ffSmrg        xvEncodingInfo *pe;
3469f606849Smrg    } u;
347fef5d1ffSmrg    int status;
348fef5d1ffSmrg
349fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
350fef5d1ffSmrg
351fef5d1ffSmrg    LockDisplay(dpy);
352fef5d1ffSmrg
353fef5d1ffSmrg    XvGetReq(QueryEncodings, req);
354fef5d1ffSmrg    req->port = port;
355fef5d1ffSmrg
356fef5d1ffSmrg    /* READ THE REPLY */
357fef5d1ffSmrg
358fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) {
359fef5d1ffSmrg        rep.num_encodings = 0;
360fef5d1ffSmrg        status = XvBadReply;
361fef5d1ffSmrg        goto out;
362fef5d1ffSmrg    }
363cdbfa18aSmrg
364fef5d1ffSmrg    size = rep.length << 2;
365fef5d1ffSmrg    if (size > 0) {
366fef5d1ffSmrg        if ((buffer = Xmalloc(size)) == NULL) {
367fef5d1ffSmrg            _XEatDataWords(dpy, rep.length);
368fef5d1ffSmrg            status = XvBadAlloc;
369fef5d1ffSmrg            goto out;
370fef5d1ffSmrg        }
371fef5d1ffSmrg        _XRead(dpy, buffer, (long) size);
372fef5d1ffSmrg    }
373fef5d1ffSmrg
374fef5d1ffSmrg    /* GET ENCODINGS */
375fef5d1ffSmrg
376fef5d1ffSmrg    if (rep.num_encodings == 0) {
377444fb138Smrg        /* If there are no encodings, there's nothing more to do. */
378fef5d1ffSmrg        status = Success;
379fef5d1ffSmrg        goto out;
380fef5d1ffSmrg    }
381fef5d1ffSmrg
382444fb138Smrg    u.buffer = buffer;
383444fb138Smrg    end = buffer + size;
384fef5d1ffSmrg
385fef5d1ffSmrg    size = rep.num_encodings * sizeof(XvEncodingInfo);
386fef5d1ffSmrg    if ((pes = Xmalloc(size)) == NULL) {
387fef5d1ffSmrg        status = XvBadAlloc;
388fef5d1ffSmrg        goto out;
389fef5d1ffSmrg    }
390fef5d1ffSmrg
391fef5d1ffSmrg    /* INITIALIZE THE ENCODING POINTER */
392fef5d1ffSmrg
393fef5d1ffSmrg    pe = pes;
394fef5d1ffSmrg    for (jj = 0; jj < rep.num_encodings; jj++) {
395fef5d1ffSmrg        pe->name = (char *) NULL;
396fef5d1ffSmrg        pe->num_encodings = 0;
397fef5d1ffSmrg        pe++;
398fef5d1ffSmrg    }
399fef5d1ffSmrg
400fef5d1ffSmrg    pe = pes;
401fef5d1ffSmrg    for (jj = 0; jj < rep.num_encodings; jj++) {
402444fb138Smrg        if (u.buffer + sz_xvEncodingInfo > end) {
403444fb138Smrg            status = XvBadReply;
404444fb138Smrg            goto out;
405444fb138Smrg        }
406fef5d1ffSmrg        pe->encoding_id = u.pe->encoding;
407fef5d1ffSmrg        pe->width = u.pe->width;
408fef5d1ffSmrg        pe->height = u.pe->height;
409fef5d1ffSmrg        pe->rate.numerator = u.pe->rate.numerator;
410fef5d1ffSmrg        pe->rate.denominator = u.pe->rate.denominator;
411fef5d1ffSmrg        pe->num_encodings = rep.num_encodings - jj;
412fef5d1ffSmrg
413fef5d1ffSmrg        size = u.pe->name_size;
414fef5d1ffSmrg        u.buffer += pad_to_int32(sz_xvEncodingInfo);
415fef5d1ffSmrg
416444fb138Smrg        if (u.buffer + size > end) {
417444fb138Smrg            status = XvBadReply;
418444fb138Smrg            goto out;
419444fb138Smrg        }
420fef5d1ffSmrg        if ((name = Xmalloc(size + 1)) == NULL) {
421fef5d1ffSmrg            status = XvBadAlloc;
422fef5d1ffSmrg            goto out;
423fef5d1ffSmrg        }
424fef5d1ffSmrg        strncpy(name, u.string, size);
425fef5d1ffSmrg        name[size] = '\0';
426fef5d1ffSmrg        pe->name = name;
427fef5d1ffSmrg        pe++;
428fef5d1ffSmrg
429fef5d1ffSmrg        u.buffer += pad_to_int32(size);
430fef5d1ffSmrg    }
431fef5d1ffSmrg
432fef5d1ffSmrg    status = Success;
433fef5d1ffSmrg
434fef5d1ffSmrg  out:
435fef5d1ffSmrg    if (status != Success) {
436fef5d1ffSmrg        XvFreeEncodingInfo(pes);
437fef5d1ffSmrg        pes = NULL;
438fef5d1ffSmrg    }
439fef5d1ffSmrg
440fef5d1ffSmrg    *p_nEncodings = rep.num_encodings;
441fef5d1ffSmrg    *p_pEncodings = pes;
442fef5d1ffSmrg
443fef5d1ffSmrg    Xfree(buffer);
444fef5d1ffSmrg    UnlockDisplay(dpy);
445fef5d1ffSmrg    SyncHandle();
446fef5d1ffSmrg
447fef5d1ffSmrg    return (Success);
4489f606849Smrg}
4499f606849Smrg
4509f606849Smrgvoid
4519f606849SmrgXvFreeEncodingInfo(XvEncodingInfo *pEncodings)
4529f606849Smrg{
453fef5d1ffSmrg    XvEncodingInfo *pe;
454fef5d1ffSmrg    unsigned long ii;
4559f606849Smrg
456fef5d1ffSmrg    if (!pEncodings)
457fef5d1ffSmrg        return;
4589f606849Smrg
459fef5d1ffSmrg    pe = pEncodings;
4609f606849Smrg
461fef5d1ffSmrg    for (ii = 0; ii < pEncodings->num_encodings; ii++, pe++) {
462fef5d1ffSmrg        if (pe->name)
463fef5d1ffSmrg            Xfree(pe->name);
464fef5d1ffSmrg    }
4659f606849Smrg
466fef5d1ffSmrg    Xfree(pEncodings);
4679f606849Smrg}
4689f606849Smrg
4699f606849Smrgint
4709f606849SmrgXvPutVideo(
471fef5d1ffSmrg    Display *dpy,
472fef5d1ffSmrg    XvPortID port,
473fef5d1ffSmrg    Drawable d,
474fef5d1ffSmrg    GC gc,
475fef5d1ffSmrg    int vx, int vy,
476fef5d1ffSmrg    unsigned int vw, unsigned int vh,
477fef5d1ffSmrg    int dx, int dy,
478fef5d1ffSmrg    unsigned int dw, unsigned int dh)
479fef5d1ffSmrg{
480fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
481fef5d1ffSmrg    xvPutVideoReq *req;
482fef5d1ffSmrg
483fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
484fef5d1ffSmrg
485fef5d1ffSmrg    LockDisplay(dpy);
486fef5d1ffSmrg
487fef5d1ffSmrg    FlushGC(dpy, gc);
488fef5d1ffSmrg
489fef5d1ffSmrg    XvGetReq(PutVideo, req);
490fef5d1ffSmrg
491fef5d1ffSmrg    req->port = port;
492fef5d1ffSmrg    req->drawable = d;
493fef5d1ffSmrg    req->gc = gc->gid;
494fef5d1ffSmrg    req->vid_x = vx;
495fef5d1ffSmrg    req->vid_y = vy;
496fef5d1ffSmrg    req->vid_w = vw;
497fef5d1ffSmrg    req->vid_h = vh;
498fef5d1ffSmrg    req->drw_x = dx;
499fef5d1ffSmrg    req->drw_y = dy;
500fef5d1ffSmrg    req->drw_w = dw;
501fef5d1ffSmrg    req->drw_h = dh;
502fef5d1ffSmrg
503fef5d1ffSmrg    UnlockDisplay(dpy);
504fef5d1ffSmrg    SyncHandle();
505fef5d1ffSmrg
506fef5d1ffSmrg    return Success;
5079f606849Smrg}
5089f606849Smrg
5099f606849Smrgint
5109f606849SmrgXvPutStill(
511fef5d1ffSmrg    Display *dpy,
512fef5d1ffSmrg    XvPortID port,
513fef5d1ffSmrg    Drawable d,
514fef5d1ffSmrg    GC gc,
515fef5d1ffSmrg    int vx, int vy,
516fef5d1ffSmrg    unsigned int vw, unsigned int vh,
517fef5d1ffSmrg    int dx, int dy,
518fef5d1ffSmrg    unsigned int dw, unsigned int dh)
519fef5d1ffSmrg{
520fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
521fef5d1ffSmrg    xvPutStillReq *req;
522fef5d1ffSmrg
523fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
524fef5d1ffSmrg
525fef5d1ffSmrg    LockDisplay(dpy);
526fef5d1ffSmrg
527fef5d1ffSmrg    FlushGC(dpy, gc);
528fef5d1ffSmrg
529fef5d1ffSmrg    XvGetReq(PutStill, req);
530fef5d1ffSmrg    req->port = port;
531fef5d1ffSmrg    req->drawable = d;
532fef5d1ffSmrg    req->gc = gc->gid;
533fef5d1ffSmrg    req->vid_x = vx;
534fef5d1ffSmrg    req->vid_y = vy;
535fef5d1ffSmrg    req->vid_w = vw;
536fef5d1ffSmrg    req->vid_h = vh;
537fef5d1ffSmrg    req->drw_x = dx;
538fef5d1ffSmrg    req->drw_y = dy;
539fef5d1ffSmrg    req->drw_w = dw;
540fef5d1ffSmrg    req->drw_h = dh;
541fef5d1ffSmrg
542fef5d1ffSmrg    UnlockDisplay(dpy);
543fef5d1ffSmrg    SyncHandle();
544fef5d1ffSmrg
545fef5d1ffSmrg    return Success;
5469f606849Smrg}
5479f606849Smrg
5489f606849Smrgint
5499f606849SmrgXvGetVideo(
550fef5d1ffSmrg    Display *dpy,
551fef5d1ffSmrg    XvPortID port,
552fef5d1ffSmrg    Drawable d,
553fef5d1ffSmrg    GC gc,
554fef5d1ffSmrg    int vx, int vy,
555fef5d1ffSmrg    unsigned int vw, unsigned int vh,
556fef5d1ffSmrg    int dx, int dy,
557fef5d1ffSmrg    unsigned int dw, unsigned int dh)
558fef5d1ffSmrg{
559fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
560fef5d1ffSmrg    xvGetVideoReq *req;
561fef5d1ffSmrg
562fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
563fef5d1ffSmrg
564fef5d1ffSmrg    LockDisplay(dpy);
565fef5d1ffSmrg
566fef5d1ffSmrg    FlushGC(dpy, gc);
567fef5d1ffSmrg
568fef5d1ffSmrg    XvGetReq(GetVideo, req);
569fef5d1ffSmrg    req->port = port;
570fef5d1ffSmrg    req->drawable = d;
571fef5d1ffSmrg    req->gc = gc->gid;
572fef5d1ffSmrg    req->vid_x = vx;
573fef5d1ffSmrg    req->vid_y = vy;
574fef5d1ffSmrg    req->vid_w = vw;
575fef5d1ffSmrg    req->vid_h = vh;
576fef5d1ffSmrg    req->drw_x = dx;
577fef5d1ffSmrg    req->drw_y = dy;
578fef5d1ffSmrg    req->drw_w = dw;
579fef5d1ffSmrg    req->drw_h = dh;
580fef5d1ffSmrg
581fef5d1ffSmrg    UnlockDisplay(dpy);
582fef5d1ffSmrg    SyncHandle();
583fef5d1ffSmrg
584fef5d1ffSmrg    return Success;
5859f606849Smrg}
5869f606849Smrg
5879f606849Smrgint
5889f606849SmrgXvGetStill(
589fef5d1ffSmrg    Display *dpy,
590fef5d1ffSmrg    XvPortID port,
591fef5d1ffSmrg    Drawable d,
592fef5d1ffSmrg    GC gc,
593fef5d1ffSmrg    int vx, int vy,
594fef5d1ffSmrg    unsigned int vw, unsigned int vh,
595fef5d1ffSmrg    int dx, int dy,
596fef5d1ffSmrg    unsigned int dw, unsigned int dh)
597fef5d1ffSmrg{
598fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
599fef5d1ffSmrg    xvGetStillReq *req;
600fef5d1ffSmrg
601fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
602fef5d1ffSmrg
603fef5d1ffSmrg    LockDisplay(dpy);
604fef5d1ffSmrg
605fef5d1ffSmrg    FlushGC(dpy, gc);
606fef5d1ffSmrg
607fef5d1ffSmrg    XvGetReq(GetStill, req);
608fef5d1ffSmrg    req->port = port;
609fef5d1ffSmrg    req->drawable = d;
610fef5d1ffSmrg    req->gc = gc->gid;
611fef5d1ffSmrg    req->vid_x = vx;
612fef5d1ffSmrg    req->vid_y = vy;
613fef5d1ffSmrg    req->vid_w = vw;
614fef5d1ffSmrg    req->vid_h = vh;
615fef5d1ffSmrg    req->drw_x = dx;
616fef5d1ffSmrg    req->drw_y = dy;
617fef5d1ffSmrg    req->drw_w = dw;
618fef5d1ffSmrg    req->drw_h = dh;
619fef5d1ffSmrg
620fef5d1ffSmrg    UnlockDisplay(dpy);
621fef5d1ffSmrg    SyncHandle();
622fef5d1ffSmrg
623fef5d1ffSmrg    return Success;
6249f606849Smrg}
6259f606849Smrg
6269f606849Smrgint
627fef5d1ffSmrgXvStopVideo(Display *dpy, XvPortID port, Drawable draw)
628fef5d1ffSmrg{
629fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
630fef5d1ffSmrg    xvStopVideoReq *req;
6319f606849Smrg
632fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
6339f606849Smrg
634fef5d1ffSmrg    LockDisplay(dpy);
6359f606849Smrg
636fef5d1ffSmrg    XvGetReq(StopVideo, req);
637fef5d1ffSmrg    req->port = port;
638fef5d1ffSmrg    req->drawable = draw;
6399f606849Smrg
640fef5d1ffSmrg    UnlockDisplay(dpy);
641fef5d1ffSmrg    SyncHandle();
6429f606849Smrg
643fef5d1ffSmrg    return Success;
6449f606849Smrg}
6459f606849Smrg
6469f606849Smrgint
647fef5d1ffSmrgXvGrabPort(Display *dpy, XvPortID port, Time time)
648fef5d1ffSmrg{
649fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
650fef5d1ffSmrg    int result;
651fef5d1ffSmrg    xvGrabPortReply rep;
652fef5d1ffSmrg    xvGrabPortReq *req;
6539f606849Smrg
654fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
6559f606849Smrg
656fef5d1ffSmrg    LockDisplay(dpy);
6579f606849Smrg
658fef5d1ffSmrg    XvGetReq(GrabPort, req);
659fef5d1ffSmrg    req->port = port;
660fef5d1ffSmrg    req->time = time;
6619f606849Smrg
662fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xTrue) == 0)
663fef5d1ffSmrg        rep.result = GrabSuccess;
6649f606849Smrg
665fef5d1ffSmrg    result = rep.result;
6669f606849Smrg
667fef5d1ffSmrg    UnlockDisplay(dpy);
668fef5d1ffSmrg    SyncHandle();
6699f606849Smrg
670fef5d1ffSmrg    return result;
6719f606849Smrg}
6729f606849Smrg
6739f606849Smrgint
674fef5d1ffSmrgXvUngrabPort(Display *dpy, XvPortID port, Time time)
675fef5d1ffSmrg{
676fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
677fef5d1ffSmrg    xvUngrabPortReq *req;
6789f606849Smrg
679fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
6809f606849Smrg
681fef5d1ffSmrg    LockDisplay(dpy);
6829f606849Smrg
683fef5d1ffSmrg    XvGetReq(UngrabPort, req);
684fef5d1ffSmrg    req->port = port;
685fef5d1ffSmrg    req->time = time;
6869f606849Smrg
687fef5d1ffSmrg    UnlockDisplay(dpy);
688fef5d1ffSmrg    SyncHandle();
6899f606849Smrg
690fef5d1ffSmrg    return Success;
6919f606849Smrg}
6929f606849Smrg
6939f606849Smrgint
694fef5d1ffSmrgXvSelectVideoNotify(Display *dpy, Drawable drawable, Bool onoff)
695fef5d1ffSmrg{
696fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
697fef5d1ffSmrg    xvSelectVideoNotifyReq *req;
6989f606849Smrg
699fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
7009f606849Smrg
701fef5d1ffSmrg    LockDisplay(dpy);
7029f606849Smrg
703fef5d1ffSmrg    XvGetReq(SelectVideoNotify, req);
704fef5d1ffSmrg    req->drawable = drawable;
705fef5d1ffSmrg    req->onoff = onoff;
7069f606849Smrg
707fef5d1ffSmrg    UnlockDisplay(dpy);
708fef5d1ffSmrg    SyncHandle();
7099f606849Smrg
710fef5d1ffSmrg    return Success;
7119f606849Smrg}
7129f606849Smrg
7139f606849Smrgint
714fef5d1ffSmrgXvSelectPortNotify(Display *dpy, XvPortID port, Bool onoff)
715fef5d1ffSmrg{
716fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
717fef5d1ffSmrg    xvSelectPortNotifyReq *req;
7189f606849Smrg
719fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
7209f606849Smrg
721fef5d1ffSmrg    LockDisplay(dpy);
7229f606849Smrg
723fef5d1ffSmrg    XvGetReq(SelectPortNotify, req);
724fef5d1ffSmrg    req->port = port;
725fef5d1ffSmrg    req->onoff = onoff;
7269f606849Smrg
727fef5d1ffSmrg    UnlockDisplay(dpy);
728fef5d1ffSmrg    SyncHandle();
7299f606849Smrg
730fef5d1ffSmrg    return Success;
7319f606849Smrg}
7329f606849Smrg
7339f606849Smrgint
734fef5d1ffSmrgXvSetPortAttribute(Display *dpy, XvPortID port, Atom attribute, int value)
7359f606849Smrg{
736fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
737fef5d1ffSmrg    xvSetPortAttributeReq *req;
7389f606849Smrg
739fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
7409f606849Smrg
741fef5d1ffSmrg    LockDisplay(dpy);
7429f606849Smrg
743fef5d1ffSmrg    XvGetReq(SetPortAttribute, req);
744fef5d1ffSmrg    req->port = port;
745fef5d1ffSmrg    req->attribute = attribute;
746fef5d1ffSmrg    req->value = value;
7479f606849Smrg
748fef5d1ffSmrg    UnlockDisplay(dpy);
749fef5d1ffSmrg    SyncHandle();
7509f606849Smrg
751fef5d1ffSmrg    return (Success);
7529f606849Smrg}
7539f606849Smrg
7549f606849Smrgint
755fef5d1ffSmrgXvGetPortAttribute(Display *dpy, XvPortID port, Atom attribute, int *p_value)
7569f606849Smrg{
757fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
758fef5d1ffSmrg    xvGetPortAttributeReq *req;
759fef5d1ffSmrg    xvGetPortAttributeReply rep;
760fef5d1ffSmrg    int status;
7619f606849Smrg
762fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
7639f606849Smrg
764fef5d1ffSmrg    LockDisplay(dpy);
7659f606849Smrg
766fef5d1ffSmrg    XvGetReq(GetPortAttribute, req);
767fef5d1ffSmrg    req->port = port;
768fef5d1ffSmrg    req->attribute = attribute;
7699f606849Smrg
770fef5d1ffSmrg    /* READ THE REPLY */
7719f606849Smrg
772fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) {
773fef5d1ffSmrg        status = XvBadReply;
774fef5d1ffSmrg    }
775fef5d1ffSmrg    else {
776fef5d1ffSmrg        *p_value = rep.value;
777fef5d1ffSmrg        status = Success;
778fef5d1ffSmrg    }
779cdbfa18aSmrg
780fef5d1ffSmrg    UnlockDisplay(dpy);
781fef5d1ffSmrg    SyncHandle();
7829f606849Smrg
783fef5d1ffSmrg    return status;
7849f606849Smrg}
7859f606849Smrg
7869f606849Smrgint
7879f606849SmrgXvQueryBestSize(
788fef5d1ffSmrg    Display *dpy,
789fef5d1ffSmrg    XvPortID port,
790fef5d1ffSmrg    Bool motion,
791fef5d1ffSmrg    unsigned int vid_w,
792fef5d1ffSmrg    unsigned int vid_h,
793fef5d1ffSmrg    unsigned int drw_w,
794fef5d1ffSmrg    unsigned int drw_h,
795fef5d1ffSmrg    unsigned int *p_actual_width,
796fef5d1ffSmrg    unsigned int *p_actual_height)
7979f606849Smrg{
798fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
799fef5d1ffSmrg    xvQueryBestSizeReq *req;
800fef5d1ffSmrg    xvQueryBestSizeReply rep;
801fef5d1ffSmrg    int status;
8029f606849Smrg
803fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
8049f606849Smrg
805fef5d1ffSmrg    LockDisplay(dpy);
8069f606849Smrg
807fef5d1ffSmrg    XvGetReq(QueryBestSize, req);
808fef5d1ffSmrg    req->port = port;
809fef5d1ffSmrg    req->motion = motion;
810fef5d1ffSmrg    req->vid_w = vid_w;
811fef5d1ffSmrg    req->vid_h = vid_h;
812fef5d1ffSmrg    req->drw_w = drw_w;
813fef5d1ffSmrg    req->drw_h = drw_h;
8149f606849Smrg
815fef5d1ffSmrg    /* READ THE REPLY */
8169f606849Smrg
817fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) {
818fef5d1ffSmrg        status = XvBadReply;
819fef5d1ffSmrg    }
820fef5d1ffSmrg    else {
821fef5d1ffSmrg        *p_actual_width = rep.actual_width;
822fef5d1ffSmrg        *p_actual_height = rep.actual_height;
823fef5d1ffSmrg        status = Success;
824fef5d1ffSmrg    }
8259f606849Smrg
826fef5d1ffSmrg    UnlockDisplay(dpy);
827fef5d1ffSmrg    SyncHandle();
8289f606849Smrg
829fef5d1ffSmrg    return status;
8309f606849Smrg}
8319f606849Smrg
8329f606849Smrg
833fef5d1ffSmrgXvAttribute *
8349f606849SmrgXvQueryPortAttributes(Display *dpy, XvPortID port, int *num)
8359f606849Smrg{
836fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
837fef5d1ffSmrg    xvQueryPortAttributesReq *req;
838fef5d1ffSmrg    xvQueryPortAttributesReply rep;
839fef5d1ffSmrg    XvAttribute *ret = NULL;
840fef5d1ffSmrg
841fef5d1ffSmrg    *num = 0;
842fef5d1ffSmrg
843fef5d1ffSmrg    XvCheckExtension(dpy, info, NULL);
844fef5d1ffSmrg
845fef5d1ffSmrg    LockDisplay(dpy);
846fef5d1ffSmrg
847fef5d1ffSmrg    XvGetReq(QueryPortAttributes, req);
848fef5d1ffSmrg    req->port = port;
849fef5d1ffSmrg
850fef5d1ffSmrg    /* READ THE REPLY */
851fef5d1ffSmrg
852fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) {
853fef5d1ffSmrg        goto out;
854fef5d1ffSmrg    }
855fef5d1ffSmrg
856fef5d1ffSmrg    /*
857fef5d1ffSmrg     * X server sends data packed as:
858fef5d1ffSmrg     *   attribute1, name1, attribute2, name2, ...
859fef5d1ffSmrg     * We allocate a single buffer large enough to hold them all and
860fef5d1ffSmrg     * then de-interleave the data so we return it to clients as:
861fef5d1ffSmrg     *   attribute1, attribute2, ..., name1, name2, ...
862fef5d1ffSmrg     * so that clients may refer to attributes as a simple array of
863fef5d1ffSmrg     * structs:  attributes[0], attributes[1], ...
864fef5d1ffSmrg     * and free it as a single/simple buffer.
865fef5d1ffSmrg     */
866fef5d1ffSmrg
867fef5d1ffSmrg    if (rep.num_attributes) {
868fef5d1ffSmrg        unsigned long size;
869fef5d1ffSmrg
870fef5d1ffSmrg        /* limit each part to no more than one half the max size */
871fef5d1ffSmrg        if ((rep.num_attributes < ((INT_MAX / 2) / sizeof(XvAttribute))) &&
872fef5d1ffSmrg            (rep.text_size < (INT_MAX / 2) - 1)) {
873fef5d1ffSmrg            size = (rep.num_attributes * sizeof(XvAttribute)) +
874fef5d1ffSmrg		rep.text_size + 1;
875fef5d1ffSmrg            ret = Xmalloc(size);
876fef5d1ffSmrg        }
877fef5d1ffSmrg
878fef5d1ffSmrg        if (ret != NULL) {
879fef5d1ffSmrg            char *marker = (char *) (&ret[rep.num_attributes]);
880fef5d1ffSmrg            xvAttributeInfo Info;
881fef5d1ffSmrg            unsigned int i;
882fef5d1ffSmrg
883fef5d1ffSmrg            /* keep track of remaining room for text strings */
884fef5d1ffSmrg            size = rep.text_size;
885fef5d1ffSmrg
886fef5d1ffSmrg            for (i = 0; i < rep.num_attributes; i++) {
887fef5d1ffSmrg                _XRead(dpy, (char *) (&Info), sz_xvAttributeInfo);
888fef5d1ffSmrg                ret[i].flags = (int) Info.flags;
889fef5d1ffSmrg                ret[i].min_value = Info.min;
890fef5d1ffSmrg                ret[i].max_value = Info.max;
891fef5d1ffSmrg                ret[i].name = marker;
892fef5d1ffSmrg                if (Info.size <= size) {
893fef5d1ffSmrg                    _XRead(dpy, marker, Info.size);
894fef5d1ffSmrg                    marker += Info.size;
895fef5d1ffSmrg                    size -= Info.size;
896fef5d1ffSmrg                }
897fef5d1ffSmrg                (*num)++;
898fef5d1ffSmrg            }
899fef5d1ffSmrg
900fef5d1ffSmrg            /* ensure final string is nil-terminated to avoid exposure of
901fef5d1ffSmrg               uninitialized memory */
902fef5d1ffSmrg            *marker = '\0';
903fef5d1ffSmrg        }
904fef5d1ffSmrg        else
905fef5d1ffSmrg            _XEatDataWords(dpy, rep.length);
906fef5d1ffSmrg    }
907fef5d1ffSmrg
908fef5d1ffSmrg  out:
909fef5d1ffSmrg    UnlockDisplay(dpy);
910fef5d1ffSmrg    SyncHandle();
911fef5d1ffSmrg
912fef5d1ffSmrg    return ret;
9139f606849Smrg}
9149f606849Smrg
915fef5d1ffSmrgXvImageFormatValues *
916fef5d1ffSmrgXvListImageFormats(Display *dpy, XvPortID port, int *num)
917fef5d1ffSmrg{
918fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
919fef5d1ffSmrg    xvListImageFormatsReq *req;
920fef5d1ffSmrg    xvListImageFormatsReply rep;
921fef5d1ffSmrg    XvImageFormatValues *ret = NULL;
922fef5d1ffSmrg
923fef5d1ffSmrg    *num = 0;
924fef5d1ffSmrg
925fef5d1ffSmrg    XvCheckExtension(dpy, info, NULL);
926fef5d1ffSmrg
927fef5d1ffSmrg    LockDisplay(dpy);
928fef5d1ffSmrg
929fef5d1ffSmrg    XvGetReq(ListImageFormats, req);
930fef5d1ffSmrg    req->port = port;
931fef5d1ffSmrg
932fef5d1ffSmrg    /* READ THE REPLY */
933fef5d1ffSmrg
934fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) {
935fef5d1ffSmrg        goto out;
936fef5d1ffSmrg    }
937fef5d1ffSmrg
938fef5d1ffSmrg    if (rep.num_formats) {
939fef5d1ffSmrg        if (rep.num_formats < (INT_MAX / sizeof(XvImageFormatValues)))
940fef5d1ffSmrg            ret = Xmalloc(rep.num_formats * sizeof(XvImageFormatValues));
941fef5d1ffSmrg
942fef5d1ffSmrg        if (ret != NULL) {
943fef5d1ffSmrg            xvImageFormatInfo Info;
944fef5d1ffSmrg            unsigned int i;
945fef5d1ffSmrg
946fef5d1ffSmrg            for (i = 0; i < rep.num_formats; i++) {
947fef5d1ffSmrg                _XRead(dpy, (char *) (&Info), sz_xvImageFormatInfo);
948fef5d1ffSmrg                ret[i].id = Info.id;
949fef5d1ffSmrg                ret[i].type = Info.type;
950fef5d1ffSmrg                ret[i].byte_order = Info.byte_order;
951fef5d1ffSmrg                memcpy(&(ret[i].guid[0]), &(Info.guid[0]), 16);
952fef5d1ffSmrg                ret[i].bits_per_pixel = Info.bpp;
953fef5d1ffSmrg                ret[i].format = Info.format;
954fef5d1ffSmrg                ret[i].num_planes = Info.num_planes;
955fef5d1ffSmrg                ret[i].depth = Info.depth;
956fef5d1ffSmrg                ret[i].red_mask = Info.red_mask;
957fef5d1ffSmrg                ret[i].green_mask = Info.green_mask;
958fef5d1ffSmrg                ret[i].blue_mask = Info.blue_mask;
959fef5d1ffSmrg                ret[i].y_sample_bits = Info.y_sample_bits;
960fef5d1ffSmrg                ret[i].u_sample_bits = Info.u_sample_bits;
961fef5d1ffSmrg                ret[i].v_sample_bits = Info.v_sample_bits;
962fef5d1ffSmrg                ret[i].horz_y_period = Info.horz_y_period;
963fef5d1ffSmrg                ret[i].horz_u_period = Info.horz_u_period;
964fef5d1ffSmrg                ret[i].horz_v_period = Info.horz_v_period;
965fef5d1ffSmrg                ret[i].vert_y_period = Info.vert_y_period;
966fef5d1ffSmrg                ret[i].vert_u_period = Info.vert_u_period;
967fef5d1ffSmrg                ret[i].vert_v_period = Info.vert_v_period;
968fef5d1ffSmrg                memcpy(&(ret[i].component_order[0]), &(Info.comp_order[0]), 32);
969fef5d1ffSmrg                ret[i].scanline_order = Info.scanline_order;
970fef5d1ffSmrg                (*num)++;
971fef5d1ffSmrg            }
972fef5d1ffSmrg        }
973fef5d1ffSmrg        else
974fef5d1ffSmrg            _XEatDataWords(dpy, rep.length);
975fef5d1ffSmrg    }
976fef5d1ffSmrg
977fef5d1ffSmrg  out:
978fef5d1ffSmrg    UnlockDisplay(dpy);
979fef5d1ffSmrg    SyncHandle();
980fef5d1ffSmrg
981fef5d1ffSmrg    return ret;
9829f606849Smrg}
9839f606849Smrg
984fef5d1ffSmrgXvImage *
985fef5d1ffSmrgXvCreateImage(
986fef5d1ffSmrg    Display *dpy,
987fef5d1ffSmrg    XvPortID port,
988fef5d1ffSmrg    int id,
989fef5d1ffSmrg    char *data,
990fef5d1ffSmrg    int width,
991fef5d1ffSmrg    int height)
992fef5d1ffSmrg{
993fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
994fef5d1ffSmrg    xvQueryImageAttributesReq *req;
995fef5d1ffSmrg    xvQueryImageAttributesReply rep;
996fef5d1ffSmrg    XvImage *ret = NULL;
997fef5d1ffSmrg
998fef5d1ffSmrg    XvCheckExtension(dpy, info, NULL);
999fef5d1ffSmrg
1000fef5d1ffSmrg    LockDisplay(dpy);
1001fef5d1ffSmrg
1002fef5d1ffSmrg    XvGetReq(QueryImageAttributes, req);
1003fef5d1ffSmrg    req->id = id;
1004fef5d1ffSmrg    req->port = port;
1005fef5d1ffSmrg    req->width = width;
1006fef5d1ffSmrg    req->height = height;
1007fef5d1ffSmrg
1008fef5d1ffSmrg    /* READ THE REPLY */
1009fef5d1ffSmrg
1010fef5d1ffSmrg    if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
1011fef5d1ffSmrg        goto out;
1012fef5d1ffSmrg    }
1013fef5d1ffSmrg
1014fef5d1ffSmrg    if (rep.num_planes < ((INT_MAX >> 3) - sizeof(XvImage)))
1015fef5d1ffSmrg        ret = Xmalloc(sizeof(XvImage) + (rep.num_planes << 3));
1016fef5d1ffSmrg
1017fef5d1ffSmrg    if (ret != NULL) {
1018fef5d1ffSmrg        ret->id = id;
1019fef5d1ffSmrg        ret->width = rep.width;
1020fef5d1ffSmrg        ret->height = rep.height;
1021fef5d1ffSmrg        ret->data_size = rep.data_size;
1022fef5d1ffSmrg        ret->num_planes = rep.num_planes;
1023fef5d1ffSmrg        ret->pitches = (int *) (&ret[1]);
1024fef5d1ffSmrg        ret->offsets = ret->pitches + rep.num_planes;
1025fef5d1ffSmrg        ret->data = data;
1026fef5d1ffSmrg        ret->obdata = NULL;
1027fef5d1ffSmrg        _XRead(dpy, (char *) (ret->pitches), rep.num_planes << 2);
1028fef5d1ffSmrg        _XRead(dpy, (char *) (ret->offsets), rep.num_planes << 2);
1029fef5d1ffSmrg    }
1030fef5d1ffSmrg    else
1031fef5d1ffSmrg        _XEatDataWords(dpy, rep.length);
1032fef5d1ffSmrg
1033fef5d1ffSmrg  out:
1034fef5d1ffSmrg    UnlockDisplay(dpy);
1035fef5d1ffSmrg    SyncHandle();
1036fef5d1ffSmrg
1037fef5d1ffSmrg    return ret;
10389f606849Smrg}
10399f606849Smrg
1040fef5d1ffSmrgXvImage *
1041fef5d1ffSmrgXvShmCreateImage(
1042fef5d1ffSmrg    Display *dpy,
1043fef5d1ffSmrg    XvPortID port,
1044fef5d1ffSmrg    int id,
1045fef5d1ffSmrg    char *data,
1046fef5d1ffSmrg    int width,
1047fef5d1ffSmrg    int height,
1048fef5d1ffSmrg    XShmSegmentInfo *shminfo)
1049fef5d1ffSmrg{
1050fef5d1ffSmrg    XvImage *ret;
10519f606849Smrg
1052fef5d1ffSmrg    ret = XvCreateImage(dpy, port, id, data, width, height);
10539f606849Smrg
1054fef5d1ffSmrg    if (ret)
1055fef5d1ffSmrg        ret->obdata = (XPointer) shminfo;
10569f606849Smrg
1057fef5d1ffSmrg    return ret;
10589f606849Smrg}
10599f606849Smrg
1060fef5d1ffSmrgint
1061fef5d1ffSmrgXvPutImage(
1062fef5d1ffSmrg    Display *dpy,
1063fef5d1ffSmrg    XvPortID port,
1064fef5d1ffSmrg    Drawable d,
1065fef5d1ffSmrg    GC gc,
1066fef5d1ffSmrg    XvImage *image,
1067fef5d1ffSmrg    int src_x, int src_y,
1068fef5d1ffSmrg    unsigned int src_w, unsigned int src_h,
1069fef5d1ffSmrg    int dest_x, int dest_y,
1070fef5d1ffSmrg    unsigned int dest_w, unsigned int dest_h)
1071fef5d1ffSmrg{
1072fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
1073fef5d1ffSmrg    xvPutImageReq *req;
1074fef5d1ffSmrg    unsigned int len;
1075fef5d1ffSmrg
1076fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
1077fef5d1ffSmrg
1078fef5d1ffSmrg    LockDisplay(dpy);
1079fef5d1ffSmrg
1080fef5d1ffSmrg    FlushGC(dpy, gc);
1081fef5d1ffSmrg
1082fef5d1ffSmrg    XvGetReq(PutImage, req);
1083fef5d1ffSmrg
1084fef5d1ffSmrg    req->port = port;
1085fef5d1ffSmrg    req->drawable = d;
1086fef5d1ffSmrg    req->gc = gc->gid;
1087fef5d1ffSmrg    req->id = image->id;
1088fef5d1ffSmrg    req->src_x = src_x;
1089fef5d1ffSmrg    req->src_y = src_y;
1090fef5d1ffSmrg    req->src_w = src_w;
1091fef5d1ffSmrg    req->src_h = src_h;
1092fef5d1ffSmrg    req->drw_x = dest_x;
1093fef5d1ffSmrg    req->drw_y = dest_y;
1094fef5d1ffSmrg    req->drw_w = dest_w;
1095fef5d1ffSmrg    req->drw_h = dest_h;
1096fef5d1ffSmrg    req->width = image->width;
1097fef5d1ffSmrg    req->height = image->height;
1098fef5d1ffSmrg
1099fef5d1ffSmrg    len = ((unsigned int) image->data_size + 3) >> 2;
1100fef5d1ffSmrg    SetReqLen(req, len, len);
1101fef5d1ffSmrg
1102fef5d1ffSmrg    /* Yes it's kindof lame that we are sending the whole thing,
1103fef5d1ffSmrg       but for video all of it may be needed even if displaying
1104fef5d1ffSmrg       only a subsection, and I don't want to go through the
1105fef5d1ffSmrg       trouble of creating subregions to send */
1106fef5d1ffSmrg    Data(dpy, (char *) image->data, image->data_size);
1107fef5d1ffSmrg
1108fef5d1ffSmrg    UnlockDisplay(dpy);
1109fef5d1ffSmrg    SyncHandle();
1110fef5d1ffSmrg
1111fef5d1ffSmrg    return Success;
11129f606849Smrg}
11139f606849Smrg
1114fef5d1ffSmrgint
1115fef5d1ffSmrgXvShmPutImage(
1116fef5d1ffSmrg    Display *dpy,
1117fef5d1ffSmrg    XvPortID port,
1118fef5d1ffSmrg    Drawable d,
1119fef5d1ffSmrg    GC gc,
1120fef5d1ffSmrg    XvImage *image,
1121fef5d1ffSmrg    int src_x, int src_y,
1122fef5d1ffSmrg    unsigned int src_w, unsigned int src_h,
1123fef5d1ffSmrg    int dest_x, int dest_y,
1124fef5d1ffSmrg    unsigned int dest_w, unsigned int dest_h,
1125fef5d1ffSmrg    Bool send_event)
1126fef5d1ffSmrg{
1127fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
1128fef5d1ffSmrg    XShmSegmentInfo *shminfo = (XShmSegmentInfo *) image->obdata;
1129fef5d1ffSmrg    xvShmPutImageReq *req;
1130fef5d1ffSmrg
1131fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
1132fef5d1ffSmrg
1133fef5d1ffSmrg    LockDisplay(dpy);
1134fef5d1ffSmrg
1135fef5d1ffSmrg    FlushGC(dpy, gc);
1136fef5d1ffSmrg
1137fef5d1ffSmrg    XvGetReq(ShmPutImage, req);
1138fef5d1ffSmrg
1139fef5d1ffSmrg    req->port = port;
1140fef5d1ffSmrg    req->drawable = d;
1141fef5d1ffSmrg    req->gc = gc->gid;
1142fef5d1ffSmrg    req->shmseg = shminfo->shmseg;
1143fef5d1ffSmrg    req->id = image->id;
1144fef5d1ffSmrg    req->src_x = src_x;
1145fef5d1ffSmrg    req->src_y = src_y;
1146fef5d1ffSmrg    req->src_w = src_w;
1147fef5d1ffSmrg    req->src_h = src_h;
1148fef5d1ffSmrg    req->drw_x = dest_x;
1149fef5d1ffSmrg    req->drw_y = dest_y;
1150fef5d1ffSmrg    req->drw_w = dest_w;
1151fef5d1ffSmrg    req->drw_h = dest_h;
1152fef5d1ffSmrg    req->offset = image->data - shminfo->shmaddr;
1153fef5d1ffSmrg    req->width = image->width;
1154fef5d1ffSmrg    req->height = image->height;
1155fef5d1ffSmrg    req->send_event = send_event;
1156fef5d1ffSmrg
1157fef5d1ffSmrg    UnlockDisplay(dpy);
1158fef5d1ffSmrg    SyncHandle();
1159fef5d1ffSmrg
1160fef5d1ffSmrg    return Success;
11619f606849Smrg}
11629f606849Smrg
11639f606849Smrg
11649f606849Smrgstatic Bool
11659f606849Smrgxv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire)
11669f606849Smrg{
1167fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
1168fef5d1ffSmrg    XvEvent *re = (XvEvent *) host;
1169fef5d1ffSmrg    xvEvent *event = (xvEvent *) wire;
11709f606849Smrg
1171fef5d1ffSmrg    XvCheckExtension(dpy, info, False);
11729f606849Smrg
1173fef5d1ffSmrg    switch ((event->u.u.type & 0x7F) - info->codes->first_event) {
11749f606849Smrg    case XvVideoNotify:
1175fef5d1ffSmrg        re->xvvideo.type = event->u.u.type & 0x7f;
1176fef5d1ffSmrg        re->xvvideo.serial = _XSetLastRequestRead(dpy, (xGenericReply *) event);
1177fef5d1ffSmrg        re->xvvideo.send_event = ((event->u.u.type & 0x80) != 0);
1178fef5d1ffSmrg        re->xvvideo.display = dpy;
1179fef5d1ffSmrg        re->xvvideo.time = event->u.videoNotify.time;
1180fef5d1ffSmrg        re->xvvideo.reason = event->u.videoNotify.reason;
1181fef5d1ffSmrg        re->xvvideo.drawable = event->u.videoNotify.drawable;
1182fef5d1ffSmrg        re->xvvideo.port_id = event->u.videoNotify.port;
1183fef5d1ffSmrg        break;
11849f606849Smrg    case XvPortNotify:
1185fef5d1ffSmrg        re->xvport.type = event->u.u.type & 0x7f;
1186fef5d1ffSmrg        re->xvport.serial = _XSetLastRequestRead(dpy, (xGenericReply *) event);
1187fef5d1ffSmrg        re->xvport.send_event = ((event->u.u.type & 0x80) != 0);
1188fef5d1ffSmrg        re->xvport.display = dpy;
1189fef5d1ffSmrg        re->xvport.time = event->u.portNotify.time;
1190fef5d1ffSmrg        re->xvport.port_id = event->u.portNotify.port;
1191fef5d1ffSmrg        re->xvport.attribute = event->u.portNotify.attribute;
1192fef5d1ffSmrg        re->xvport.value = event->u.portNotify.value;
1193fef5d1ffSmrg        break;
11949f606849Smrg    default:
1195fef5d1ffSmrg        return False;
1196fef5d1ffSmrg    }
11979f606849Smrg
1198fef5d1ffSmrg    return (True);
11999f606849Smrg}
1200