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    }
195dc088bc7Smrg    else if (rep.num_adaptors != 0) {
196dc088bc7Smrg        status = XvBadReply;
197dc088bc7Smrg        goto out;
198dc088bc7Smrg    }
199fef5d1ffSmrg
200fef5d1ffSmrg    /* GET INPUT ADAPTORS */
201fef5d1ffSmrg
202fef5d1ffSmrg    if (rep.num_adaptors == 0) {
203444fb138Smrg        /* If there are no adaptors, there's nothing more to do. */
204fef5d1ffSmrg        status = Success;
205fef5d1ffSmrg        goto out;
206fef5d1ffSmrg    }
207fef5d1ffSmrg
208444fb138Smrg    u.buffer = buffer;
209444fb138Smrg    end = buffer + size;
210fef5d1ffSmrg
211dc088bc7Smrg    if ((pas = Xcalloc(rep.num_adaptors, sizeof(XvAdaptorInfo))) == NULL) {
212fef5d1ffSmrg        status = XvBadAlloc;
213fef5d1ffSmrg        goto out;
214fef5d1ffSmrg    }
215fef5d1ffSmrg
216fef5d1ffSmrg    /* INIT ADAPTOR FIELDS */
217fef5d1ffSmrg
218fef5d1ffSmrg    pa = pas;
219949d0342Smrg    for (unsigned int ii = 0; ii < rep.num_adaptors; ii++) {
220949d0342Smrg        char *name;
221949d0342Smrg
222444fb138Smrg        if (u.buffer + sz_xvAdaptorInfo > end) {
223444fb138Smrg            status = XvBadReply;
224444fb138Smrg            goto out;
225444fb138Smrg        }
226949d0342Smrg        pa->type = (char) u.pa->type;
227fef5d1ffSmrg        pa->base_id = u.pa->base_id;
228fef5d1ffSmrg        pa->num_ports = u.pa->num_ports;
229fef5d1ffSmrg        pa->num_formats = u.pa->num_formats;
230fef5d1ffSmrg        pa->num_adaptors = rep.num_adaptors - ii;
231fef5d1ffSmrg
232fef5d1ffSmrg        /* GET ADAPTOR NAME */
233fef5d1ffSmrg
234fef5d1ffSmrg        size = u.pa->name_size;
235fef5d1ffSmrg        u.buffer += pad_to_int32(sz_xvAdaptorInfo);
236fef5d1ffSmrg
237444fb138Smrg        if (u.buffer + size > end) {
238444fb138Smrg            status = XvBadReply;
239444fb138Smrg            goto out;
240444fb138Smrg        }
241fef5d1ffSmrg        if ((name = Xmalloc(size + 1)) == NULL) {
242fef5d1ffSmrg            status = XvBadAlloc;
243fef5d1ffSmrg            goto out;
244fef5d1ffSmrg        }
245fef5d1ffSmrg        (void) strncpy(name, u.string, size);
246fef5d1ffSmrg        name[size] = '\0';
247fef5d1ffSmrg        pa->name = name;
248fef5d1ffSmrg
249fef5d1ffSmrg        u.buffer += pad_to_int32(size);
250cdbfa18aSmrg
251fef5d1ffSmrg        /* GET FORMATS */
252fef5d1ffSmrg
253dc088bc7Smrg        if ((pfs = Xcalloc(pa->num_formats, sizeof(XvFormat))) == NULL) {
254fef5d1ffSmrg            status = XvBadAlloc;
255fef5d1ffSmrg            goto out;
256fef5d1ffSmrg        }
257fef5d1ffSmrg
258fef5d1ffSmrg        pf = pfs;
259949d0342Smrg        for (unsigned int jj = 0; jj < pa->num_formats; jj++) {
260444fb138Smrg            if (u.buffer + sz_xvFormat > end) {
261444fb138Smrg                Xfree(pfs);
262444fb138Smrg                status = XvBadReply;
263444fb138Smrg                goto out;
264444fb138Smrg            }
265949d0342Smrg            pf->depth = (char) u.pf->depth;
266fef5d1ffSmrg            pf->visual_id = u.pf->visual;
267fef5d1ffSmrg            pf++;
268fef5d1ffSmrg
269fef5d1ffSmrg            u.buffer += pad_to_int32(sz_xvFormat);
270fef5d1ffSmrg        }
271fef5d1ffSmrg
272fef5d1ffSmrg        pa->formats = pfs;
273fef5d1ffSmrg
274fef5d1ffSmrg        pa++;
275fef5d1ffSmrg
276fef5d1ffSmrg    }
277fef5d1ffSmrg
278fef5d1ffSmrg    status = Success;
279fef5d1ffSmrg
280fef5d1ffSmrg  out:
281fef5d1ffSmrg    if (status != Success) {
282fef5d1ffSmrg        XvFreeAdaptorInfo(pas);
283fef5d1ffSmrg        pas = NULL;
284fef5d1ffSmrg    }
285fef5d1ffSmrg
286fef5d1ffSmrg    *p_nAdaptors = rep.num_adaptors;
287fef5d1ffSmrg    *p_pAdaptors = pas;
288fef5d1ffSmrg
289fef5d1ffSmrg    Xfree(buffer);
290fef5d1ffSmrg    UnlockDisplay(dpy);
291fef5d1ffSmrg    SyncHandle();
292fef5d1ffSmrg
293fef5d1ffSmrg    return status;
2949f606849Smrg}
2959f606849Smrg
2969f606849Smrg
2979f606849Smrgvoid
2989f606849SmrgXvFreeAdaptorInfo(XvAdaptorInfo *pAdaptors)
2999f606849Smrg{
300fef5d1ffSmrg    XvAdaptorInfo *pa;
3019f606849Smrg
302fef5d1ffSmrg    if (!pAdaptors)
303fef5d1ffSmrg        return;
3049f606849Smrg
305fef5d1ffSmrg    pa = pAdaptors;
3069f606849Smrg
307949d0342Smrg    for (unsigned int ii = 0; ii < pAdaptors->num_adaptors; ii++, pa++) {
308fef5d1ffSmrg        if (pa->name) {
309fef5d1ffSmrg            Xfree(pa->name);
310fef5d1ffSmrg        }
311fef5d1ffSmrg        if (pa->formats) {
312fef5d1ffSmrg            Xfree(pa->formats);
313fef5d1ffSmrg        }
314cdbfa18aSmrg    }
3159f606849Smrg
316fef5d1ffSmrg    Xfree(pAdaptors);
3179f606849Smrg}
3189f606849Smrg
3199f606849Smrgint
3209f606849SmrgXvQueryEncodings(
321fef5d1ffSmrg    Display *dpy,
322fef5d1ffSmrg    XvPortID port,
323fef5d1ffSmrg    unsigned int *p_nEncodings,
324fef5d1ffSmrg    XvEncodingInfo ** p_pEncodings)
325fef5d1ffSmrg{
326fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
327fef5d1ffSmrg    xvQueryEncodingsReq *req;
328fef5d1ffSmrg    xvQueryEncodingsReply rep;
329fef5d1ffSmrg    size_t size;
330fef5d1ffSmrg    XvEncodingInfo *pes = NULL, *pe;
331fef5d1ffSmrg    char *buffer = NULL;
332949d0342Smrg    char *end;
333fef5d1ffSmrg    union {
334fef5d1ffSmrg        char *buffer;
335fef5d1ffSmrg        char *string;
336fef5d1ffSmrg        xvEncodingInfo *pe;
3379f606849Smrg    } u;
338fef5d1ffSmrg    int status;
339fef5d1ffSmrg
340fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
341fef5d1ffSmrg
342fef5d1ffSmrg    LockDisplay(dpy);
343fef5d1ffSmrg
344fef5d1ffSmrg    XvGetReq(QueryEncodings, req);
345949d0342Smrg    req->port = (CARD32) port;
346fef5d1ffSmrg
347fef5d1ffSmrg    /* READ THE REPLY */
348fef5d1ffSmrg
349fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) {
350fef5d1ffSmrg        rep.num_encodings = 0;
351fef5d1ffSmrg        status = XvBadReply;
352fef5d1ffSmrg        goto out;
353fef5d1ffSmrg    }
354cdbfa18aSmrg
355fef5d1ffSmrg    size = rep.length << 2;
356fef5d1ffSmrg    if (size > 0) {
357fef5d1ffSmrg        if ((buffer = Xmalloc(size)) == NULL) {
358fef5d1ffSmrg            _XEatDataWords(dpy, rep.length);
359fef5d1ffSmrg            status = XvBadAlloc;
360fef5d1ffSmrg            goto out;
361fef5d1ffSmrg        }
362fef5d1ffSmrg        _XRead(dpy, buffer, (long) size);
363fef5d1ffSmrg    }
364dc088bc7Smrg    else if (rep.num_encodings != 0) {
365dc088bc7Smrg        status = XvBadReply;
366dc088bc7Smrg        goto out;
367dc088bc7Smrg    }
368fef5d1ffSmrg
369fef5d1ffSmrg    /* GET ENCODINGS */
370fef5d1ffSmrg
371fef5d1ffSmrg    if (rep.num_encodings == 0) {
372444fb138Smrg        /* If there are no encodings, there's nothing more to do. */
373fef5d1ffSmrg        status = Success;
374fef5d1ffSmrg        goto out;
375fef5d1ffSmrg    }
376fef5d1ffSmrg
377444fb138Smrg    u.buffer = buffer;
378444fb138Smrg    end = buffer + size;
379fef5d1ffSmrg
380dc088bc7Smrg    if ((pes = Xcalloc(rep.num_encodings, sizeof(XvEncodingInfo))) == NULL) {
381fef5d1ffSmrg        status = XvBadAlloc;
382fef5d1ffSmrg        goto out;
383fef5d1ffSmrg    }
384fef5d1ffSmrg
385fef5d1ffSmrg    /* INITIALIZE THE ENCODING POINTER */
386fef5d1ffSmrg
387fef5d1ffSmrg    pe = pes;
388949d0342Smrg    for (unsigned int jj = 0; jj < rep.num_encodings; jj++) {
389949d0342Smrg        char *name;
390949d0342Smrg
391444fb138Smrg        if (u.buffer + sz_xvEncodingInfo > end) {
392444fb138Smrg            status = XvBadReply;
393444fb138Smrg            goto out;
394444fb138Smrg        }
395fef5d1ffSmrg        pe->encoding_id = u.pe->encoding;
396fef5d1ffSmrg        pe->width = u.pe->width;
397fef5d1ffSmrg        pe->height = u.pe->height;
398fef5d1ffSmrg        pe->rate.numerator = u.pe->rate.numerator;
399fef5d1ffSmrg        pe->rate.denominator = u.pe->rate.denominator;
400fef5d1ffSmrg        pe->num_encodings = rep.num_encodings - jj;
401fef5d1ffSmrg
402fef5d1ffSmrg        size = u.pe->name_size;
403fef5d1ffSmrg        u.buffer += pad_to_int32(sz_xvEncodingInfo);
404fef5d1ffSmrg
405444fb138Smrg        if (u.buffer + size > end) {
406444fb138Smrg            status = XvBadReply;
407444fb138Smrg            goto out;
408444fb138Smrg        }
409fef5d1ffSmrg        if ((name = Xmalloc(size + 1)) == NULL) {
410fef5d1ffSmrg            status = XvBadAlloc;
411fef5d1ffSmrg            goto out;
412fef5d1ffSmrg        }
413fef5d1ffSmrg        strncpy(name, u.string, size);
414fef5d1ffSmrg        name[size] = '\0';
415fef5d1ffSmrg        pe->name = name;
416fef5d1ffSmrg        pe++;
417fef5d1ffSmrg
418fef5d1ffSmrg        u.buffer += pad_to_int32(size);
419fef5d1ffSmrg    }
420fef5d1ffSmrg
421fef5d1ffSmrg    status = Success;
422fef5d1ffSmrg
423fef5d1ffSmrg  out:
424fef5d1ffSmrg    if (status != Success) {
425fef5d1ffSmrg        XvFreeEncodingInfo(pes);
426fef5d1ffSmrg        pes = NULL;
427fef5d1ffSmrg    }
428fef5d1ffSmrg
429fef5d1ffSmrg    *p_nEncodings = rep.num_encodings;
430fef5d1ffSmrg    *p_pEncodings = pes;
431fef5d1ffSmrg
432fef5d1ffSmrg    Xfree(buffer);
433fef5d1ffSmrg    UnlockDisplay(dpy);
434fef5d1ffSmrg    SyncHandle();
435fef5d1ffSmrg
436fef5d1ffSmrg    return (Success);
4379f606849Smrg}
4389f606849Smrg
4399f606849Smrgvoid
4409f606849SmrgXvFreeEncodingInfo(XvEncodingInfo *pEncodings)
4419f606849Smrg{
442fef5d1ffSmrg    XvEncodingInfo *pe;
4439f606849Smrg
444fef5d1ffSmrg    if (!pEncodings)
445fef5d1ffSmrg        return;
4469f606849Smrg
447fef5d1ffSmrg    pe = pEncodings;
4489f606849Smrg
449949d0342Smrg    for (unsigned long ii = 0; ii < pEncodings->num_encodings; ii++, pe++) {
450fef5d1ffSmrg        if (pe->name)
451fef5d1ffSmrg            Xfree(pe->name);
452fef5d1ffSmrg    }
4539f606849Smrg
454fef5d1ffSmrg    Xfree(pEncodings);
4559f606849Smrg}
4569f606849Smrg
4579f606849Smrgint
4589f606849SmrgXvPutVideo(
459fef5d1ffSmrg    Display *dpy,
460fef5d1ffSmrg    XvPortID port,
461fef5d1ffSmrg    Drawable d,
462fef5d1ffSmrg    GC gc,
463fef5d1ffSmrg    int vx, int vy,
464fef5d1ffSmrg    unsigned int vw, unsigned int vh,
465fef5d1ffSmrg    int dx, int dy,
466fef5d1ffSmrg    unsigned int dw, unsigned int dh)
467fef5d1ffSmrg{
468fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
469fef5d1ffSmrg    xvPutVideoReq *req;
470fef5d1ffSmrg
471fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
472fef5d1ffSmrg
473fef5d1ffSmrg    LockDisplay(dpy);
474fef5d1ffSmrg
475fef5d1ffSmrg    FlushGC(dpy, gc);
476fef5d1ffSmrg
477fef5d1ffSmrg    XvGetReq(PutVideo, req);
478fef5d1ffSmrg
479949d0342Smrg    req->port = (CARD32) port;
480949d0342Smrg    req->drawable = (CARD32) d;
481949d0342Smrg    req->gc = (CARD32) gc->gid;
482949d0342Smrg    req->vid_x = (INT16) vx;
483949d0342Smrg    req->vid_y = (INT16) vy;
484949d0342Smrg    req->vid_w = (CARD16) vw;
485949d0342Smrg    req->vid_h = (CARD16) vh;
486949d0342Smrg    req->drw_x = (INT16) dx;
487949d0342Smrg    req->drw_y = (INT16) dy;
488949d0342Smrg    req->drw_w = (CARD16) dw;
489949d0342Smrg    req->drw_h = (CARD16) dh;
490fef5d1ffSmrg
491fef5d1ffSmrg    UnlockDisplay(dpy);
492fef5d1ffSmrg    SyncHandle();
493fef5d1ffSmrg
494fef5d1ffSmrg    return Success;
4959f606849Smrg}
4969f606849Smrg
4979f606849Smrgint
4989f606849SmrgXvPutStill(
499fef5d1ffSmrg    Display *dpy,
500fef5d1ffSmrg    XvPortID port,
501fef5d1ffSmrg    Drawable d,
502fef5d1ffSmrg    GC gc,
503fef5d1ffSmrg    int vx, int vy,
504fef5d1ffSmrg    unsigned int vw, unsigned int vh,
505fef5d1ffSmrg    int dx, int dy,
506fef5d1ffSmrg    unsigned int dw, unsigned int dh)
507fef5d1ffSmrg{
508fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
509fef5d1ffSmrg    xvPutStillReq *req;
510fef5d1ffSmrg
511fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
512fef5d1ffSmrg
513fef5d1ffSmrg    LockDisplay(dpy);
514fef5d1ffSmrg
515fef5d1ffSmrg    FlushGC(dpy, gc);
516fef5d1ffSmrg
517fef5d1ffSmrg    XvGetReq(PutStill, req);
518949d0342Smrg    req->port = (CARD32) port;
519949d0342Smrg    req->drawable = (CARD32) d;
520949d0342Smrg    req->gc = (CARD32) gc->gid;
521949d0342Smrg    req->vid_x = (INT16) vx;
522949d0342Smrg    req->vid_y = (INT16) vy;
523949d0342Smrg    req->vid_w = (CARD16) vw;
524949d0342Smrg    req->vid_h = (CARD16) vh;
525949d0342Smrg    req->drw_x = (INT16) dx;
526949d0342Smrg    req->drw_y = (INT16) dy;
527949d0342Smrg    req->drw_w = (CARD16) dw;
528949d0342Smrg    req->drw_h = (CARD16) dh;
529fef5d1ffSmrg
530fef5d1ffSmrg    UnlockDisplay(dpy);
531fef5d1ffSmrg    SyncHandle();
532fef5d1ffSmrg
533fef5d1ffSmrg    return Success;
5349f606849Smrg}
5359f606849Smrg
5369f606849Smrgint
5379f606849SmrgXvGetVideo(
538fef5d1ffSmrg    Display *dpy,
539fef5d1ffSmrg    XvPortID port,
540fef5d1ffSmrg    Drawable d,
541fef5d1ffSmrg    GC gc,
542fef5d1ffSmrg    int vx, int vy,
543fef5d1ffSmrg    unsigned int vw, unsigned int vh,
544fef5d1ffSmrg    int dx, int dy,
545fef5d1ffSmrg    unsigned int dw, unsigned int dh)
546fef5d1ffSmrg{
547fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
548fef5d1ffSmrg    xvGetVideoReq *req;
549fef5d1ffSmrg
550fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
551fef5d1ffSmrg
552fef5d1ffSmrg    LockDisplay(dpy);
553fef5d1ffSmrg
554fef5d1ffSmrg    FlushGC(dpy, gc);
555fef5d1ffSmrg
556fef5d1ffSmrg    XvGetReq(GetVideo, req);
557949d0342Smrg    req->port = (CARD32) port;
558949d0342Smrg    req->drawable = (CARD32) d;
559949d0342Smrg    req->gc = (CARD32) gc->gid;
560949d0342Smrg    req->vid_x = (INT16) vx;
561949d0342Smrg    req->vid_y = (INT16) vy;
562949d0342Smrg    req->vid_w = (CARD16) vw;
563949d0342Smrg    req->vid_h = (CARD16) vh;
564949d0342Smrg    req->drw_x = (INT16) dx;
565949d0342Smrg    req->drw_y = (INT16) dy;
566949d0342Smrg    req->drw_w = (CARD16) dw;
567949d0342Smrg    req->drw_h = (CARD16) dh;
568fef5d1ffSmrg
569fef5d1ffSmrg    UnlockDisplay(dpy);
570fef5d1ffSmrg    SyncHandle();
571fef5d1ffSmrg
572fef5d1ffSmrg    return Success;
5739f606849Smrg}
5749f606849Smrg
5759f606849Smrgint
5769f606849SmrgXvGetStill(
577fef5d1ffSmrg    Display *dpy,
578fef5d1ffSmrg    XvPortID port,
579fef5d1ffSmrg    Drawable d,
580fef5d1ffSmrg    GC gc,
581fef5d1ffSmrg    int vx, int vy,
582fef5d1ffSmrg    unsigned int vw, unsigned int vh,
583fef5d1ffSmrg    int dx, int dy,
584fef5d1ffSmrg    unsigned int dw, unsigned int dh)
585fef5d1ffSmrg{
586fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
587fef5d1ffSmrg    xvGetStillReq *req;
588fef5d1ffSmrg
589fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
590fef5d1ffSmrg
591fef5d1ffSmrg    LockDisplay(dpy);
592fef5d1ffSmrg
593fef5d1ffSmrg    FlushGC(dpy, gc);
594fef5d1ffSmrg
595fef5d1ffSmrg    XvGetReq(GetStill, req);
596949d0342Smrg    req->port = (CARD32) port;
597949d0342Smrg    req->drawable = (CARD32) d;
598949d0342Smrg    req->gc = (CARD32) gc->gid;
599949d0342Smrg    req->vid_x = (INT16) vx;
600949d0342Smrg    req->vid_y = (INT16) vy;
601949d0342Smrg    req->vid_w = (CARD16) vw;
602949d0342Smrg    req->vid_h = (CARD16) vh;
603949d0342Smrg    req->drw_x = (INT16) dx;
604949d0342Smrg    req->drw_y = (INT16) dy;
605949d0342Smrg    req->drw_w = (CARD16) dw;
606949d0342Smrg    req->drw_h = (CARD16) dh;
607fef5d1ffSmrg
608fef5d1ffSmrg    UnlockDisplay(dpy);
609fef5d1ffSmrg    SyncHandle();
610fef5d1ffSmrg
611fef5d1ffSmrg    return Success;
6129f606849Smrg}
6139f606849Smrg
6149f606849Smrgint
615fef5d1ffSmrgXvStopVideo(Display *dpy, XvPortID port, Drawable draw)
616fef5d1ffSmrg{
617fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
618fef5d1ffSmrg    xvStopVideoReq *req;
6199f606849Smrg
620fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
6219f606849Smrg
622fef5d1ffSmrg    LockDisplay(dpy);
6239f606849Smrg
624fef5d1ffSmrg    XvGetReq(StopVideo, req);
625949d0342Smrg    req->port = (CARD32) port;
626949d0342Smrg    req->drawable = (CARD32) draw;
6279f606849Smrg
628fef5d1ffSmrg    UnlockDisplay(dpy);
629fef5d1ffSmrg    SyncHandle();
6309f606849Smrg
631fef5d1ffSmrg    return Success;
6329f606849Smrg}
6339f606849Smrg
6349f606849Smrgint
635fef5d1ffSmrgXvGrabPort(Display *dpy, XvPortID port, Time time)
636fef5d1ffSmrg{
637fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
638fef5d1ffSmrg    int result;
639fef5d1ffSmrg    xvGrabPortReply rep;
640fef5d1ffSmrg    xvGrabPortReq *req;
6419f606849Smrg
642fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
6439f606849Smrg
644fef5d1ffSmrg    LockDisplay(dpy);
6459f606849Smrg
646fef5d1ffSmrg    XvGetReq(GrabPort, req);
647949d0342Smrg    req->port = (CARD32) port;
648949d0342Smrg    req->time = (CARD32) time;
6499f606849Smrg
650fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xTrue) == 0)
651fef5d1ffSmrg        rep.result = GrabSuccess;
6529f606849Smrg
653fef5d1ffSmrg    result = rep.result;
6549f606849Smrg
655fef5d1ffSmrg    UnlockDisplay(dpy);
656fef5d1ffSmrg    SyncHandle();
6579f606849Smrg
658fef5d1ffSmrg    return result;
6599f606849Smrg}
6609f606849Smrg
6619f606849Smrgint
662fef5d1ffSmrgXvUngrabPort(Display *dpy, XvPortID port, Time time)
663fef5d1ffSmrg{
664fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
665fef5d1ffSmrg    xvUngrabPortReq *req;
6669f606849Smrg
667fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
6689f606849Smrg
669fef5d1ffSmrg    LockDisplay(dpy);
6709f606849Smrg
671fef5d1ffSmrg    XvGetReq(UngrabPort, req);
672949d0342Smrg    req->port = (CARD32) port;
673949d0342Smrg    req->time = (CARD32) time;
6749f606849Smrg
675fef5d1ffSmrg    UnlockDisplay(dpy);
676fef5d1ffSmrg    SyncHandle();
6779f606849Smrg
678fef5d1ffSmrg    return Success;
6799f606849Smrg}
6809f606849Smrg
6819f606849Smrgint
682fef5d1ffSmrgXvSelectVideoNotify(Display *dpy, Drawable drawable, Bool onoff)
683fef5d1ffSmrg{
684fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
685fef5d1ffSmrg    xvSelectVideoNotifyReq *req;
6869f606849Smrg
687fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
6889f606849Smrg
689fef5d1ffSmrg    LockDisplay(dpy);
6909f606849Smrg
691fef5d1ffSmrg    XvGetReq(SelectVideoNotify, req);
692949d0342Smrg    req->drawable = (CARD32) drawable;
693949d0342Smrg    req->onoff = (BOOL) onoff;
6949f606849Smrg
695fef5d1ffSmrg    UnlockDisplay(dpy);
696fef5d1ffSmrg    SyncHandle();
6979f606849Smrg
698fef5d1ffSmrg    return Success;
6999f606849Smrg}
7009f606849Smrg
7019f606849Smrgint
702fef5d1ffSmrgXvSelectPortNotify(Display *dpy, XvPortID port, Bool onoff)
703fef5d1ffSmrg{
704fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
705fef5d1ffSmrg    xvSelectPortNotifyReq *req;
7069f606849Smrg
707fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
7089f606849Smrg
709fef5d1ffSmrg    LockDisplay(dpy);
7109f606849Smrg
711fef5d1ffSmrg    XvGetReq(SelectPortNotify, req);
712949d0342Smrg    req->port = (CARD32) port;
713949d0342Smrg    req->onoff = (BOOL) onoff;
7149f606849Smrg
715fef5d1ffSmrg    UnlockDisplay(dpy);
716fef5d1ffSmrg    SyncHandle();
7179f606849Smrg
718fef5d1ffSmrg    return Success;
7199f606849Smrg}
7209f606849Smrg
7219f606849Smrgint
722fef5d1ffSmrgXvSetPortAttribute(Display *dpy, XvPortID port, Atom attribute, int value)
7239f606849Smrg{
724fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
725fef5d1ffSmrg    xvSetPortAttributeReq *req;
7269f606849Smrg
727fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
7289f606849Smrg
729fef5d1ffSmrg    LockDisplay(dpy);
7309f606849Smrg
731fef5d1ffSmrg    XvGetReq(SetPortAttribute, req);
732949d0342Smrg    req->port = (CARD32) port;
733949d0342Smrg    req->attribute = (CARD32) attribute;
734fef5d1ffSmrg    req->value = value;
7359f606849Smrg
736fef5d1ffSmrg    UnlockDisplay(dpy);
737fef5d1ffSmrg    SyncHandle();
7389f606849Smrg
739fef5d1ffSmrg    return (Success);
7409f606849Smrg}
7419f606849Smrg
7429f606849Smrgint
743fef5d1ffSmrgXvGetPortAttribute(Display *dpy, XvPortID port, Atom attribute, int *p_value)
7449f606849Smrg{
745fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
746fef5d1ffSmrg    xvGetPortAttributeReq *req;
747fef5d1ffSmrg    xvGetPortAttributeReply rep;
748fef5d1ffSmrg    int status;
7499f606849Smrg
750fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
7519f606849Smrg
752fef5d1ffSmrg    LockDisplay(dpy);
7539f606849Smrg
754fef5d1ffSmrg    XvGetReq(GetPortAttribute, req);
755949d0342Smrg    req->port = (CARD32) port;
756949d0342Smrg    req->attribute = (CARD32) attribute;
7579f606849Smrg
758fef5d1ffSmrg    /* READ THE REPLY */
7599f606849Smrg
760fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) {
761fef5d1ffSmrg        status = XvBadReply;
762fef5d1ffSmrg    }
763fef5d1ffSmrg    else {
764fef5d1ffSmrg        *p_value = rep.value;
765fef5d1ffSmrg        status = Success;
766fef5d1ffSmrg    }
767cdbfa18aSmrg
768fef5d1ffSmrg    UnlockDisplay(dpy);
769fef5d1ffSmrg    SyncHandle();
7709f606849Smrg
771fef5d1ffSmrg    return status;
7729f606849Smrg}
7739f606849Smrg
7749f606849Smrgint
7759f606849SmrgXvQueryBestSize(
776fef5d1ffSmrg    Display *dpy,
777fef5d1ffSmrg    XvPortID port,
778fef5d1ffSmrg    Bool motion,
779fef5d1ffSmrg    unsigned int vid_w,
780fef5d1ffSmrg    unsigned int vid_h,
781fef5d1ffSmrg    unsigned int drw_w,
782fef5d1ffSmrg    unsigned int drw_h,
783fef5d1ffSmrg    unsigned int *p_actual_width,
784fef5d1ffSmrg    unsigned int *p_actual_height)
7859f606849Smrg{
786fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
787fef5d1ffSmrg    xvQueryBestSizeReq *req;
788fef5d1ffSmrg    xvQueryBestSizeReply rep;
789fef5d1ffSmrg    int status;
7909f606849Smrg
791fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
7929f606849Smrg
793fef5d1ffSmrg    LockDisplay(dpy);
7949f606849Smrg
795fef5d1ffSmrg    XvGetReq(QueryBestSize, req);
796949d0342Smrg    req->port = (CARD32) port;
797949d0342Smrg    req->motion = (CARD8) motion;
798949d0342Smrg    req->vid_w = (CARD16) vid_w;
799949d0342Smrg    req->vid_h = (CARD16) vid_h;
800949d0342Smrg    req->drw_w = (CARD16) drw_w;
801949d0342Smrg    req->drw_h = (CARD16) drw_h;
8029f606849Smrg
803fef5d1ffSmrg    /* READ THE REPLY */
8049f606849Smrg
805fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) {
806fef5d1ffSmrg        status = XvBadReply;
807fef5d1ffSmrg    }
808fef5d1ffSmrg    else {
809fef5d1ffSmrg        *p_actual_width = rep.actual_width;
810fef5d1ffSmrg        *p_actual_height = rep.actual_height;
811fef5d1ffSmrg        status = Success;
812fef5d1ffSmrg    }
8139f606849Smrg
814fef5d1ffSmrg    UnlockDisplay(dpy);
815fef5d1ffSmrg    SyncHandle();
8169f606849Smrg
817fef5d1ffSmrg    return status;
8189f606849Smrg}
8199f606849Smrg
8209f606849Smrg
821fef5d1ffSmrgXvAttribute *
8229f606849SmrgXvQueryPortAttributes(Display *dpy, XvPortID port, int *num)
8239f606849Smrg{
824fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
825fef5d1ffSmrg    xvQueryPortAttributesReq *req;
826fef5d1ffSmrg    xvQueryPortAttributesReply rep;
827fef5d1ffSmrg    XvAttribute *ret = NULL;
828fef5d1ffSmrg
829fef5d1ffSmrg    *num = 0;
830fef5d1ffSmrg
831fef5d1ffSmrg    XvCheckExtension(dpy, info, NULL);
832fef5d1ffSmrg
833fef5d1ffSmrg    LockDisplay(dpy);
834fef5d1ffSmrg
835fef5d1ffSmrg    XvGetReq(QueryPortAttributes, req);
836949d0342Smrg    req->port = (CARD32) port;
837fef5d1ffSmrg
838fef5d1ffSmrg    /* READ THE REPLY */
839fef5d1ffSmrg
840fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) {
841fef5d1ffSmrg        goto out;
842fef5d1ffSmrg    }
843fef5d1ffSmrg
844fef5d1ffSmrg    /*
845fef5d1ffSmrg     * X server sends data packed as:
846fef5d1ffSmrg     *   attribute1, name1, attribute2, name2, ...
847fef5d1ffSmrg     * We allocate a single buffer large enough to hold them all and
848fef5d1ffSmrg     * then de-interleave the data so we return it to clients as:
849fef5d1ffSmrg     *   attribute1, attribute2, ..., name1, name2, ...
850fef5d1ffSmrg     * so that clients may refer to attributes as a simple array of
851fef5d1ffSmrg     * structs:  attributes[0], attributes[1], ...
852fef5d1ffSmrg     * and free it as a single/simple buffer.
853fef5d1ffSmrg     */
854fef5d1ffSmrg
855fef5d1ffSmrg    if (rep.num_attributes) {
856fef5d1ffSmrg        /* limit each part to no more than one half the max size */
857fef5d1ffSmrg        if ((rep.num_attributes < ((INT_MAX / 2) / sizeof(XvAttribute))) &&
858fef5d1ffSmrg            (rep.text_size < (INT_MAX / 2) - 1)) {
859949d0342Smrg            unsigned long size;
860949d0342Smrg
861fef5d1ffSmrg            size = (rep.num_attributes * sizeof(XvAttribute)) +
862fef5d1ffSmrg		rep.text_size + 1;
863fef5d1ffSmrg            ret = Xmalloc(size);
864fef5d1ffSmrg        }
865fef5d1ffSmrg
866fef5d1ffSmrg        if (ret != NULL) {
867fef5d1ffSmrg            char *marker = (char *) (&ret[rep.num_attributes]);
868fef5d1ffSmrg            xvAttributeInfo Info;
869fef5d1ffSmrg
870fef5d1ffSmrg            /* keep track of remaining room for text strings */
871949d0342Smrg            unsigned long size = rep.text_size;
872fef5d1ffSmrg
873949d0342Smrg            for (unsigned int i = 0; i < rep.num_attributes; i++) {
874fef5d1ffSmrg                _XRead(dpy, (char *) (&Info), sz_xvAttributeInfo);
875fef5d1ffSmrg                ret[i].flags = (int) Info.flags;
876fef5d1ffSmrg                ret[i].min_value = Info.min;
877fef5d1ffSmrg                ret[i].max_value = Info.max;
878fef5d1ffSmrg                ret[i].name = marker;
879fef5d1ffSmrg                if (Info.size <= size) {
880fef5d1ffSmrg                    _XRead(dpy, marker, Info.size);
881fef5d1ffSmrg                    marker += Info.size;
882fef5d1ffSmrg                    size -= Info.size;
883fef5d1ffSmrg                }
884fef5d1ffSmrg                (*num)++;
885fef5d1ffSmrg            }
886fef5d1ffSmrg
887fef5d1ffSmrg            /* ensure final string is nil-terminated to avoid exposure of
888fef5d1ffSmrg               uninitialized memory */
889fef5d1ffSmrg            *marker = '\0';
890fef5d1ffSmrg        }
891fef5d1ffSmrg        else
892fef5d1ffSmrg            _XEatDataWords(dpy, rep.length);
893fef5d1ffSmrg    }
894fef5d1ffSmrg
895fef5d1ffSmrg  out:
896fef5d1ffSmrg    UnlockDisplay(dpy);
897fef5d1ffSmrg    SyncHandle();
898fef5d1ffSmrg
899fef5d1ffSmrg    return ret;
9009f606849Smrg}
9019f606849Smrg
902fef5d1ffSmrgXvImageFormatValues *
903fef5d1ffSmrgXvListImageFormats(Display *dpy, XvPortID port, int *num)
904fef5d1ffSmrg{
905fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
906fef5d1ffSmrg    xvListImageFormatsReq *req;
907fef5d1ffSmrg    xvListImageFormatsReply rep;
908fef5d1ffSmrg    XvImageFormatValues *ret = NULL;
909fef5d1ffSmrg
910fef5d1ffSmrg    *num = 0;
911fef5d1ffSmrg
912fef5d1ffSmrg    XvCheckExtension(dpy, info, NULL);
913fef5d1ffSmrg
914fef5d1ffSmrg    LockDisplay(dpy);
915fef5d1ffSmrg
916fef5d1ffSmrg    XvGetReq(ListImageFormats, req);
917949d0342Smrg    req->port = (CARD32) port;
918fef5d1ffSmrg
919fef5d1ffSmrg    /* READ THE REPLY */
920fef5d1ffSmrg
921fef5d1ffSmrg    if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) {
922fef5d1ffSmrg        goto out;
923fef5d1ffSmrg    }
924fef5d1ffSmrg
925fef5d1ffSmrg    if (rep.num_formats) {
926fef5d1ffSmrg        if (rep.num_formats < (INT_MAX / sizeof(XvImageFormatValues)))
927dc088bc7Smrg            ret = Xcalloc(rep.num_formats, sizeof(XvImageFormatValues));
928fef5d1ffSmrg
929fef5d1ffSmrg        if (ret != NULL) {
930949d0342Smrg            for (unsigned int i = 0; i < rep.num_formats; i++) {
931949d0342Smrg                xvImageFormatInfo Info;
932fef5d1ffSmrg
933fef5d1ffSmrg                _XRead(dpy, (char *) (&Info), sz_xvImageFormatInfo);
934949d0342Smrg                ret[i].id = (int) Info.id;
935fef5d1ffSmrg                ret[i].type = Info.type;
936fef5d1ffSmrg                ret[i].byte_order = Info.byte_order;
937fef5d1ffSmrg                memcpy(&(ret[i].guid[0]), &(Info.guid[0]), 16);
938fef5d1ffSmrg                ret[i].bits_per_pixel = Info.bpp;
939fef5d1ffSmrg                ret[i].format = Info.format;
940fef5d1ffSmrg                ret[i].num_planes = Info.num_planes;
941fef5d1ffSmrg                ret[i].depth = Info.depth;
942fef5d1ffSmrg                ret[i].red_mask = Info.red_mask;
943fef5d1ffSmrg                ret[i].green_mask = Info.green_mask;
944fef5d1ffSmrg                ret[i].blue_mask = Info.blue_mask;
945fef5d1ffSmrg                ret[i].y_sample_bits = Info.y_sample_bits;
946fef5d1ffSmrg                ret[i].u_sample_bits = Info.u_sample_bits;
947fef5d1ffSmrg                ret[i].v_sample_bits = Info.v_sample_bits;
948fef5d1ffSmrg                ret[i].horz_y_period = Info.horz_y_period;
949fef5d1ffSmrg                ret[i].horz_u_period = Info.horz_u_period;
950fef5d1ffSmrg                ret[i].horz_v_period = Info.horz_v_period;
951fef5d1ffSmrg                ret[i].vert_y_period = Info.vert_y_period;
952fef5d1ffSmrg                ret[i].vert_u_period = Info.vert_u_period;
953fef5d1ffSmrg                ret[i].vert_v_period = Info.vert_v_period;
954fef5d1ffSmrg                memcpy(&(ret[i].component_order[0]), &(Info.comp_order[0]), 32);
955fef5d1ffSmrg                ret[i].scanline_order = Info.scanline_order;
956fef5d1ffSmrg                (*num)++;
957fef5d1ffSmrg            }
958fef5d1ffSmrg        }
959fef5d1ffSmrg        else
960fef5d1ffSmrg            _XEatDataWords(dpy, rep.length);
961fef5d1ffSmrg    }
962fef5d1ffSmrg
963fef5d1ffSmrg  out:
964fef5d1ffSmrg    UnlockDisplay(dpy);
965fef5d1ffSmrg    SyncHandle();
966fef5d1ffSmrg
967fef5d1ffSmrg    return ret;
9689f606849Smrg}
9699f606849Smrg
970fef5d1ffSmrgXvImage *
971fef5d1ffSmrgXvCreateImage(
972fef5d1ffSmrg    Display *dpy,
973fef5d1ffSmrg    XvPortID port,
974fef5d1ffSmrg    int id,
975fef5d1ffSmrg    char *data,
976fef5d1ffSmrg    int width,
977fef5d1ffSmrg    int height)
978fef5d1ffSmrg{
979fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
980fef5d1ffSmrg    xvQueryImageAttributesReq *req;
981fef5d1ffSmrg    xvQueryImageAttributesReply rep;
982fef5d1ffSmrg    XvImage *ret = NULL;
983fef5d1ffSmrg
984fef5d1ffSmrg    XvCheckExtension(dpy, info, NULL);
985fef5d1ffSmrg
986fef5d1ffSmrg    LockDisplay(dpy);
987fef5d1ffSmrg
988fef5d1ffSmrg    XvGetReq(QueryImageAttributes, req);
989949d0342Smrg    req->id = (CARD32) id;
990949d0342Smrg    req->port = (CARD32) port;
991949d0342Smrg    req->width = (CARD16) width;
992949d0342Smrg    req->height = (CARD16) height;
993fef5d1ffSmrg
994fef5d1ffSmrg    /* READ THE REPLY */
995fef5d1ffSmrg
996fef5d1ffSmrg    if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
997fef5d1ffSmrg        goto out;
998fef5d1ffSmrg    }
999fef5d1ffSmrg
1000fef5d1ffSmrg    if (rep.num_planes < ((INT_MAX >> 3) - sizeof(XvImage)))
1001fef5d1ffSmrg        ret = Xmalloc(sizeof(XvImage) + (rep.num_planes << 3));
1002fef5d1ffSmrg
1003fef5d1ffSmrg    if (ret != NULL) {
1004fef5d1ffSmrg        ret->id = id;
1005fef5d1ffSmrg        ret->width = rep.width;
1006fef5d1ffSmrg        ret->height = rep.height;
1007949d0342Smrg        ret->data_size = (int) rep.data_size;
1008949d0342Smrg        ret->num_planes = (int) rep.num_planes;
1009fef5d1ffSmrg        ret->pitches = (int *) (&ret[1]);
1010fef5d1ffSmrg        ret->offsets = ret->pitches + rep.num_planes;
1011fef5d1ffSmrg        ret->data = data;
1012fef5d1ffSmrg        ret->obdata = NULL;
1013fef5d1ffSmrg        _XRead(dpy, (char *) (ret->pitches), rep.num_planes << 2);
1014fef5d1ffSmrg        _XRead(dpy, (char *) (ret->offsets), rep.num_planes << 2);
1015fef5d1ffSmrg    }
1016fef5d1ffSmrg    else
1017fef5d1ffSmrg        _XEatDataWords(dpy, rep.length);
1018fef5d1ffSmrg
1019fef5d1ffSmrg  out:
1020fef5d1ffSmrg    UnlockDisplay(dpy);
1021fef5d1ffSmrg    SyncHandle();
1022fef5d1ffSmrg
1023fef5d1ffSmrg    return ret;
10249f606849Smrg}
10259f606849Smrg
1026fef5d1ffSmrgXvImage *
1027fef5d1ffSmrgXvShmCreateImage(
1028fef5d1ffSmrg    Display *dpy,
1029fef5d1ffSmrg    XvPortID port,
1030fef5d1ffSmrg    int id,
1031fef5d1ffSmrg    char *data,
1032fef5d1ffSmrg    int width,
1033fef5d1ffSmrg    int height,
1034fef5d1ffSmrg    XShmSegmentInfo *shminfo)
1035fef5d1ffSmrg{
1036fef5d1ffSmrg    XvImage *ret;
10379f606849Smrg
1038fef5d1ffSmrg    ret = XvCreateImage(dpy, port, id, data, width, height);
10399f606849Smrg
1040fef5d1ffSmrg    if (ret)
1041fef5d1ffSmrg        ret->obdata = (XPointer) shminfo;
10429f606849Smrg
1043fef5d1ffSmrg    return ret;
10449f606849Smrg}
10459f606849Smrg
1046fef5d1ffSmrgint
1047fef5d1ffSmrgXvPutImage(
1048fef5d1ffSmrg    Display *dpy,
1049fef5d1ffSmrg    XvPortID port,
1050fef5d1ffSmrg    Drawable d,
1051fef5d1ffSmrg    GC gc,
1052fef5d1ffSmrg    XvImage *image,
1053fef5d1ffSmrg    int src_x, int src_y,
1054fef5d1ffSmrg    unsigned int src_w, unsigned int src_h,
1055fef5d1ffSmrg    int dest_x, int dest_y,
1056fef5d1ffSmrg    unsigned int dest_w, unsigned int dest_h)
1057fef5d1ffSmrg{
1058fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
1059fef5d1ffSmrg    xvPutImageReq *req;
1060fef5d1ffSmrg    unsigned int len;
1061fef5d1ffSmrg
1062fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
1063fef5d1ffSmrg
1064fef5d1ffSmrg    LockDisplay(dpy);
1065fef5d1ffSmrg
1066fef5d1ffSmrg    FlushGC(dpy, gc);
1067fef5d1ffSmrg
1068fef5d1ffSmrg    XvGetReq(PutImage, req);
1069fef5d1ffSmrg
1070949d0342Smrg    req->port = (CARD32) port;
1071949d0342Smrg    req->drawable = (CARD32) d;
1072949d0342Smrg    req->gc = (CARD32) gc->gid;
1073949d0342Smrg    req->id = (CARD32) image->id;
1074949d0342Smrg    req->src_x = (INT16) src_x;
1075949d0342Smrg    req->src_y = (INT16) src_y;
1076949d0342Smrg    req->src_w = (CARD16) src_w;
1077949d0342Smrg    req->src_h = (CARD16) src_h;
1078949d0342Smrg    req->drw_x = (INT16) dest_x;
1079949d0342Smrg    req->drw_y = (INT16) dest_y;
1080949d0342Smrg    req->drw_w = (CARD16) dest_w;
1081949d0342Smrg    req->drw_h = (CARD16) dest_h;
1082949d0342Smrg    req->width = (CARD16) image->width;
1083949d0342Smrg    req->height = (CARD16) image->height;
1084fef5d1ffSmrg
1085fef5d1ffSmrg    len = ((unsigned int) image->data_size + 3) >> 2;
1086fef5d1ffSmrg    SetReqLen(req, len, len);
1087fef5d1ffSmrg
1088fef5d1ffSmrg    /* Yes it's kindof lame that we are sending the whole thing,
1089fef5d1ffSmrg       but for video all of it may be needed even if displaying
1090fef5d1ffSmrg       only a subsection, and I don't want to go through the
1091fef5d1ffSmrg       trouble of creating subregions to send */
1092fef5d1ffSmrg    Data(dpy, (char *) image->data, image->data_size);
1093fef5d1ffSmrg
1094fef5d1ffSmrg    UnlockDisplay(dpy);
1095fef5d1ffSmrg    SyncHandle();
1096fef5d1ffSmrg
1097fef5d1ffSmrg    return Success;
10989f606849Smrg}
10999f606849Smrg
1100fef5d1ffSmrgint
1101fef5d1ffSmrgXvShmPutImage(
1102fef5d1ffSmrg    Display *dpy,
1103fef5d1ffSmrg    XvPortID port,
1104fef5d1ffSmrg    Drawable d,
1105fef5d1ffSmrg    GC gc,
1106fef5d1ffSmrg    XvImage *image,
1107fef5d1ffSmrg    int src_x, int src_y,
1108fef5d1ffSmrg    unsigned int src_w, unsigned int src_h,
1109fef5d1ffSmrg    int dest_x, int dest_y,
1110fef5d1ffSmrg    unsigned int dest_w, unsigned int dest_h,
1111fef5d1ffSmrg    Bool send_event)
1112fef5d1ffSmrg{
1113fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
1114fef5d1ffSmrg    XShmSegmentInfo *shminfo = (XShmSegmentInfo *) image->obdata;
1115fef5d1ffSmrg    xvShmPutImageReq *req;
1116fef5d1ffSmrg
1117fef5d1ffSmrg    XvCheckExtension(dpy, info, XvBadExtension);
1118fef5d1ffSmrg
1119fef5d1ffSmrg    LockDisplay(dpy);
1120fef5d1ffSmrg
1121fef5d1ffSmrg    FlushGC(dpy, gc);
1122fef5d1ffSmrg
1123fef5d1ffSmrg    XvGetReq(ShmPutImage, req);
1124fef5d1ffSmrg
1125949d0342Smrg    req->port = (CARD32) port;
1126949d0342Smrg    req->drawable = (CARD32) d;
1127949d0342Smrg    req->gc = (CARD32) gc->gid;
1128949d0342Smrg    req->shmseg = (CARD32) shminfo->shmseg;
1129949d0342Smrg    req->id = (CARD32) image->id;
1130949d0342Smrg    req->src_x = (INT16) src_x;
1131949d0342Smrg    req->src_y = (INT16) src_y;
1132949d0342Smrg    req->src_w = (CARD16) src_w;
1133949d0342Smrg    req->src_h = (CARD16) src_h;
1134949d0342Smrg    req->drw_x = (INT16) dest_x;
1135949d0342Smrg    req->drw_y = (INT16) dest_y;
1136949d0342Smrg    req->drw_w = (CARD16) dest_w;
1137949d0342Smrg    req->drw_h = (CARD16) dest_h;
1138949d0342Smrg    req->offset = (CARD32) (image->data - shminfo->shmaddr);
1139949d0342Smrg    req->width = (CARD16) image->width;
1140949d0342Smrg    req->height = (CARD16) image->height;
1141949d0342Smrg    req->send_event = (CARD8) send_event;
1142fef5d1ffSmrg
1143fef5d1ffSmrg    UnlockDisplay(dpy);
1144fef5d1ffSmrg    SyncHandle();
1145fef5d1ffSmrg
1146fef5d1ffSmrg    return Success;
11479f606849Smrg}
11489f606849Smrg
11499f606849Smrg
11509f606849Smrgstatic Bool
11519f606849Smrgxv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire)
11529f606849Smrg{
1153fef5d1ffSmrg    XExtDisplayInfo *info = xv_find_display(dpy);
1154fef5d1ffSmrg    XvEvent *re = (XvEvent *) host;
1155fef5d1ffSmrg    xvEvent *event = (xvEvent *) wire;
11569f606849Smrg
1157fef5d1ffSmrg    XvCheckExtension(dpy, info, False);
11589f606849Smrg
1159fef5d1ffSmrg    switch ((event->u.u.type & 0x7F) - info->codes->first_event) {
11609f606849Smrg    case XvVideoNotify:
1161fef5d1ffSmrg        re->xvvideo.type = event->u.u.type & 0x7f;
1162fef5d1ffSmrg        re->xvvideo.serial = _XSetLastRequestRead(dpy, (xGenericReply *) event);
1163fef5d1ffSmrg        re->xvvideo.send_event = ((event->u.u.type & 0x80) != 0);
1164fef5d1ffSmrg        re->xvvideo.display = dpy;
1165fef5d1ffSmrg        re->xvvideo.time = event->u.videoNotify.time;
1166fef5d1ffSmrg        re->xvvideo.reason = event->u.videoNotify.reason;
1167fef5d1ffSmrg        re->xvvideo.drawable = event->u.videoNotify.drawable;
1168fef5d1ffSmrg        re->xvvideo.port_id = event->u.videoNotify.port;
1169fef5d1ffSmrg        break;
11709f606849Smrg    case XvPortNotify:
1171fef5d1ffSmrg        re->xvport.type = event->u.u.type & 0x7f;
1172fef5d1ffSmrg        re->xvport.serial = _XSetLastRequestRead(dpy, (xGenericReply *) event);
1173fef5d1ffSmrg        re->xvport.send_event = ((event->u.u.type & 0x80) != 0);
1174fef5d1ffSmrg        re->xvport.display = dpy;
1175fef5d1ffSmrg        re->xvport.time = event->u.portNotify.time;
1176fef5d1ffSmrg        re->xvport.port_id = event->u.portNotify.port;
1177fef5d1ffSmrg        re->xvport.attribute = event->u.portNotify.attribute;
1178fef5d1ffSmrg        re->xvport.value = event->u.portNotify.value;
1179fef5d1ffSmrg        break;
11809f606849Smrg    default:
1181fef5d1ffSmrg        return False;
1182fef5d1ffSmrg    }
11839f606849Smrg
1184fef5d1ffSmrg    return (True);
11859f606849Smrg}
1186