1/*****************************************************************************
2 * XvMC Wrapper including the Nonstandard VLD extension.
3 *
4 * Copyright (c) 2004 The Unichrome project. All rights reserved.
5 *
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHOR(S) OR COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 *
25 * Author: Thomas Hellström (2004)
26 */
27
28/*
29 * BUGS: The wrapper really should maintain one symbol table per port.
30 * This could possibly be implemented. To do that, the port-independent
31 * symbols need to be lifted out, and one would have to create a number
32 * of mapping tables:
33 *
34 *                 port  -> symbol table
35 *                 context -> port
36 *                 surface -> port
37 *                 subpicture -> port
38 *
39 * and reference the right table when needed.
40 * This needs to be done only if there is a player that wants to access two
41 * displays with different hardware simultaneously. Not likely as of today.
42 */
43
44#ifdef HAVE_CONFIG_H
45#include "config.h"
46#endif
47
48#include <X11/Xlib.h>
49#include <X11/extensions/XvMC.h>
50#include <X11/extensions/XvMClib.h>
51#include "X11/extensions/vldXvMC.h"
52#include <dlfcn.h>
53#include <stdio.h>
54#include <string.h>
55#include <ctype.h>
56#include <stdlib.h>
57
58typedef Bool (*XvMCQueryExtensionP) (Display *, int *, int *);
59typedef Status (*XvMCQueryVersionP) (Display *, int *, int *);
60typedef XvMCSurfaceInfo *(*XvMCListSurfaceTypesP) (Display *, XvPortID, int *);
61typedef Status (*XvMCCreateContextP) (Display *, XvPortID, int, int, int, int,
62                                      XvMCContext *);
63typedef Status (*XvMCDestroyContextP) (Display *, XvMCContext *);
64typedef Status (*XvMCCreateSurfaceP) (Display *, XvMCContext *, XvMCSurface *);
65typedef Status (*XvMCDestroySurfaceP) (Display *, XvMCSurface *);
66typedef XvImageFormatValues *(*XvMCListSubpictureTypesP)(Display *, XvPortID,
67                                                         int, int *);
68typedef Status (*XvMCPutSurfaceP) (Display *, XvMCSurface *, Drawable, short,
69                                   short, unsigned short, unsigned short, short,
70                                   short, unsigned short, unsigned short, int);
71typedef Status (*XvMCHideSurfaceP) (Display *, XvMCSurface *);
72typedef Status (*XvMCCreateSubpictureP) (Display *, XvMCContext *,
73                                         XvMCSubpicture *, unsigned short,
74                                         unsigned short, int);
75typedef Status (*XvMCClearSubpictureP) (Display *, XvMCSubpicture *, short,
76                                        short, unsigned short, unsigned short,
77                                        unsigned int);
78typedef Status (*XvMCCompositeSubpictureP) (Display *, XvMCSubpicture *,
79                                            XvImage *, short, short,
80                                            unsigned short, unsigned short,
81                                            short, short);
82typedef Status (*XvMCDestroySubpictureP) (Display *, XvMCSubpicture *);
83typedef Status (*XvMCSetSubpicturePaletteP) (Display *, XvMCSubpicture *,
84                                             unsigned char *);
85typedef Status (*XvMCBlendSubpictureP) (Display * d, XvMCSurface *,
86                                        XvMCSubpicture *, short, short,
87                                        unsigned short, unsigned short, short,
88                                        short, unsigned short, unsigned short);
89typedef Status (*XvMCBlendSubpicture2P) (Display *, XvMCSurface *, XvMCSurface *,
90                                         XvMCSubpicture *, short, short,
91                                         unsigned short, unsigned short, short,
92                                         short, unsigned short, unsigned short);
93typedef Status (*XvMCSyncSurfaceP) (Display *, XvMCSurface *);
94typedef Status (*XvMCFlushSurfaceP) (Display *, XvMCSurface *);
95typedef Status (*XvMCGetSurfaceStatusP) (Display *, XvMCSurface *, int *);
96typedef Status (*XvMCRenderSurfaceP) (Display *, XvMCContext *, unsigned int,
97                                      XvMCSurface *, XvMCSurface *,
98                                      XvMCSurface *, unsigned int, unsigned int,
99                                      unsigned int, XvMCMacroBlockArray *,
100                                      XvMCBlockArray *);
101typedef Status (*XvMCSyncSubpictureP) (Display *, XvMCSubpicture *);
102typedef Status (*XvMCFlushSubpictureP) (Display *, XvMCSubpicture *);
103typedef Status (*XvMCGetSubpictureStatusP) (Display *, XvMCSubpicture *, int *);
104typedef Status (*XvMCCreateBlocksP) (Display *, XvMCContext *, unsigned int,
105                                     XvMCBlockArray *);
106typedef Status (*XvMCDestroyBlocksP) (Display *, XvMCBlockArray *);
107typedef Status (*XvMCCreateMacroBlocksP) (Display *, XvMCContext *, unsigned int,
108                                          XvMCMacroBlockArray *);
109typedef Status (*XvMCDestroyMacroBlocksP) (Display *, XvMCMacroBlockArray *);
110typedef XvAttribute *(*XvMCQueryAttributesP)(Display *, XvMCContext *, int *);
111typedef Status (*XvMCSetAttributeP) (Display *, XvMCContext *, Atom, int);
112typedef Status (*XvMCGetAttributeP) (Display *, XvMCContext *, Atom, int *);
113
114/*
115 * Nonstandard VLD acceleration level:
116 */
117
118typedef Status (*XvMCBeginSurfaceP) (Display *, XvMCContext *, XvMCSurface *,
119                                     XvMCSurface *, XvMCSurface * f,
120                                     const XvMCMpegControl *);
121typedef Status (*XvMCLoadQMatrixP) (Display *, XvMCContext *,
122                                    const XvMCQMatrix *);
123typedef Status (*XvMCPutSliceP) (Display *, XvMCContext *, char *, int);
124typedef Status (*XvMCPutSlice2P) (Display *, XvMCContext *, char *, int, int);
125typedef Status (*XvMCGetDRInfoP) (Display *, XvPortID, char **, char **, int *,
126                                  int *, int *, int *);
127
128typedef struct {
129    XvMCQueryExtensionP         XvMCQueryExtension;
130    XvMCQueryVersionP           XvMCQueryVersion;
131    XvMCListSurfaceTypesP       XvMCListSurfaceTypes;
132    XvMCCreateContextP          XvMCCreateContext;
133    XvMCDestroyContextP         XvMCDestroyContext;
134    XvMCCreateSurfaceP          XvMCCreateSurface;
135    XvMCDestroySurfaceP         XvMCDestroySurface;
136    XvMCListSubpictureTypesP    XvMCListSubpictureTypes;
137    XvMCPutSurfaceP             XvMCPutSurface;
138    XvMCHideSurfaceP            XvMCHideSurface;
139    XvMCCreateSubpictureP       XvMCCreateSubpicture;
140    XvMCClearSubpictureP        XvMCClearSubpicture;
141    XvMCCompositeSubpictureP    XvMCCompositeSubpicture;
142    XvMCDestroySubpictureP      XvMCDestroySubpicture;
143    XvMCSetSubpicturePaletteP   XvMCSetSubpicturePalette;
144    XvMCBlendSubpictureP        XvMCBlendSubpicture;
145    XvMCBlendSubpicture2P       XvMCBlendSubpicture2;
146    XvMCSyncSurfaceP            XvMCSyncSurface;
147    XvMCFlushSurfaceP           XvMCFlushSurface;
148    XvMCGetSurfaceStatusP       XvMCGetSurfaceStatus;
149    XvMCRenderSurfaceP          XvMCRenderSurface;
150    XvMCSyncSubpictureP         XvMCSyncSubpicture;
151    XvMCFlushSubpictureP        XvMCFlushSubpicture;
152    XvMCGetSubpictureStatusP    XvMCGetSubpictureStatus;
153    XvMCCreateBlocksP           XvMCCreateBlocks;
154    XvMCDestroyBlocksP          XvMCDestroyBlocks;
155    XvMCCreateMacroBlocksP      XvMCCreateMacroBlocks;
156    XvMCDestroyMacroBlocksP     XvMCDestroyMacroBlocks;
157    XvMCQueryAttributesP        XvMCQueryAttributes;
158    XvMCSetAttributeP           XvMCSetAttribute;
159    XvMCGetAttributeP           XvMCGetAttribute;
160
161    /*
162     * Nonstandard VLD acceleration level:
163     */
164
165    XvMCBeginSurfaceP           XvMCBeginSurface;
166    XvMCLoadQMatrixP            XvMCLoadQMatrix;
167    XvMCPutSliceP               XvMCPutSlice;
168    XvMCPutSlice2P              XvMCPutSlice2;
169
170    /*
171     * Driver name function.
172     */
173
174    XvMCGetDRInfoP               XvMCGetDRInfo;
175
176    int preInitialised;
177    int initialised;
178    int vldextension;
179} XvMCWrapper;
180
181static XvMCWrapper xW;
182static int wrapperInit = 0;
183static int wrapperPreInit = 0;
184static void *xvhandle;
185static void *handle2;
186
187#define BUFLEN 200
188
189#define STRS(ARG) STR(ARG)
190#define STR(ARG) #ARG
191
192#define XW_RSYM(base,handle,handle2,pointer, retval)			\
193    do {								\
194	register char *symerr;						\
195	base.pointer = (pointer##P) dlsym((handle),#pointer);		\
196	if ((symerr = dlerror()) != NULL) {				\
197	    if (!handle2) {						\
198		fprintf(stderr,"%s\n",symerr); return retval;		\
199	    }								\
200	    base.pointer = (pointer##P) dlsym((handle2),#pointer);	\
201	    if ((symerr = dlerror()) != NULL) {				\
202		fprintf(stderr,"%s\n",symerr); return retval;		\
203	    }								\
204	}								\
205    } while (0);
206
207#define XW_RSYM2(base,handle,handle2,pointer)			\
208    base.pointer = (pointer##P) dlsym((handle),#pointer);	\
209    if (dlerror() != NULL) {					\
210	base.pointer = (pointer##P) dlsym((handle2),#pointer);	\
211	if (dlerror() != NULL) return;				\
212    }
213
214/*
215 * Try to dlopen a shared library, versionless first.
216 */
217
218static void *
219dlopenversion(const char *lib, const char *version, int flag)
220{
221    void *ret;
222    size_t curLen, verLen;
223    char *curName;
224
225    curLen = strlen(lib) + (verLen = strlen(version)) + 1;
226    curName = (char *) malloc(curLen * sizeof(char));
227    strncpy(curName, lib, curLen);
228    if (verLen > 1) {
229        const char *tail = strstr(version + 1, ".");
230
231        if (NULL != tail) {
232            strncat(curName, version, (size_t) (tail - version));
233        }
234        else {
235            strncat(curName, version, verLen);
236        }
237    }
238    ret = dlopen(curName, flag);
239    free(curName);
240    return ret;
241}
242
243static int
244preInitW(Display *dpy)
245{
246
247    /*
248     * Resolve functions that are not hw driver specific.
249     */
250
251    void *handleZ = NULL;
252
253    wrapperPreInit = 1;
254    xW.preInitialised = 0;
255    xW.initialised = 0;
256    xvhandle = dlopenversion("libXv.so", XV_SOVERSION, RTLD_LAZY | RTLD_GLOBAL);
257    if (!xvhandle) {
258        fprintf(stderr, "XvMCWrapper: Warning! Could not open shared "
259                "library \"libXv.so" XV_SOVERSION
260                "\"\nThis may cause relocation "
261                "errors later.\nError was: \"%s\".\n", dlerror());
262    }
263    handle2 =
264        dlopenversion("libXvMC.so", XVMC_SOVERSION, RTLD_LAZY | RTLD_GLOBAL);
265    if (!handle2) {
266        fprintf(stderr, "XvMCWrapper: Could not load XvMC "
267                "library \"libXvMC.so" XVMC_SOVERSION "\". Failing\n");
268        fprintf(stderr, "%s\n", dlerror());
269        return 1;
270    }
271    XW_RSYM(xW, handle2, handleZ, XvMCQueryExtension, 1);
272    XW_RSYM(xW, handle2, handleZ, XvMCQueryVersion, 1);
273    xW.preInitialised = 1;
274    return 0;
275}
276
277static void
278initW(Display *dpy, XvPortID port)
279{
280    char nameBuffer[BUFLEN];
281    void *handle;
282    char *clientName = NULL;
283    char *err;
284    size_t nameLen = 0;
285
286    wrapperInit = 1;
287    xW.initialised = 0;
288
289    if (!wrapperPreInit)
290        if (preInitW(dpy))
291            return;
292
293    /*
294     * Will the DDX tell us the client driver name?
295     */
296
297    xW.XvMCGetDRInfo = (XvMCGetDRInfoP)
298        dlsym(handle2, "XvMCGetDRInfo");
299
300    if ((err = dlerror()) == NULL) {
301        int major, minor, patchLevel, isLocal;
302        char *busID = NULL;
303
304        if (0 == xW.XvMCGetDRInfo(dpy, port, &clientName, &busID, &major,
305                                  &minor, &patchLevel, &isLocal)) {
306            nameLen = strlen(clientName);
307            XFree(busID);
308            if (!isLocal) {
309                fprintf(stderr,
310                        "XvMCWrapper: X server is not local. Cannot run XvMC.\n");
311                XFree(clientName);
312                return;
313            }
314        }
315        else {
316            clientName = NULL;
317        }
318    }
319
320    if (clientName && (nameLen < BUFLEN - 7) && (nameLen > 0)) {
321        nameLen += 3;
322        strncpy(nameBuffer, "lib", BUFLEN - 1);
323        strncpy(nameBuffer + 3, clientName, BUFLEN - 4);
324        strncpy(nameBuffer + nameLen, ".so", BUFLEN - nameLen - 1);
325        nameBuffer[BUFLEN - 1] = 0;
326        XFree(clientName);
327        handle = dlopenversion(nameBuffer, XVMC_SOVERSION, RTLD_LAZY);
328    }
329    else {
330        /*
331         * No. Try to obtain it from the config file.
332         */
333
334        size_t tmp;
335        FILE *configFile;
336
337        if (clientName)
338            XFree(clientName);
339
340        configFile = fopen(STRS(XVMC_CONFIGDIR) "/XvMCConfig", "r");
341
342        xW.initialised = 0;
343        xW.vldextension = 0;
344
345        if (NULL == configFile) {
346            fprintf(stderr, "XvMCWrapper: Could not open config file \"%s\".\n",
347                    STRS(XVMC_CONFIGDIR) "/XvMCConfig");
348            perror("XvMCWrapper");
349            return;
350        }
351
352        if (NULL == fgets(nameBuffer, BUFLEN, configFile)) {
353            fclose(configFile);
354            fprintf(stderr, "XvMCWrapper: Could not read XvMC library name.\n");
355            perror("XvMCWrapper");
356            return;
357        }
358
359        fclose(configFile);
360        if ((tmp = strlen(nameBuffer)) == 0) {
361            fprintf(stderr, "XvMCWrapper: Zero length XvMC library name.\n");
362            fprintf(stderr, "%s\n", dlerror());
363            return;
364        }
365
366        /*
367         * Skip trailing newlines and garbage.
368         */
369
370        while (iscntrl(nameBuffer[tmp - 1])) {
371            nameBuffer[tmp - 1] = 0;
372            if (--tmp == 0) {
373                fprintf(stderr,
374                        "XvMCWrapper: Zero length XvMC library name.\n");
375                return;
376            }
377        }
378        handle = dlopen(nameBuffer, RTLD_LAZY);
379    }
380    if (!handle) {
381        fprintf(stderr, "XvMCWrapper: Could not load hardware specific XvMC "
382                "library \"%s\".\n", nameBuffer);
383        fprintf(stderr, "%s\n", dlerror());
384        return;
385    }
386
387    XW_RSYM(xW, handle, handle2, XvMCListSurfaceTypes,);
388    XW_RSYM(xW, handle, handle2, XvMCCreateContext,);
389    XW_RSYM(xW, handle, handle2, XvMCDestroyContext,);
390    XW_RSYM(xW, handle, handle2, XvMCCreateSurface,);
391    XW_RSYM(xW, handle, handle2, XvMCDestroySurface,);
392    XW_RSYM(xW, handle, handle2, XvMCListSubpictureTypes,);
393    XW_RSYM(xW, handle, handle2, XvMCHideSurface,);
394    XW_RSYM(xW, handle, handle2, XvMCCreateSubpicture,);
395    XW_RSYM(xW, handle, handle2, XvMCClearSubpicture,);
396    XW_RSYM(xW, handle, handle2, XvMCCompositeSubpicture,);
397    XW_RSYM(xW, handle, handle2, XvMCDestroySubpicture,);
398    XW_RSYM(xW, handle, handle2, XvMCSetSubpicturePalette,);
399    XW_RSYM(xW, handle, handle2, XvMCBlendSubpicture,);
400    XW_RSYM(xW, handle, handle2, XvMCBlendSubpicture2,);
401    XW_RSYM(xW, handle, handle2, XvMCPutSurface,);
402    XW_RSYM(xW, handle, handle2, XvMCSyncSurface,);
403    XW_RSYM(xW, handle, handle2, XvMCFlushSurface,);
404    XW_RSYM(xW, handle, handle2, XvMCGetSurfaceStatus,);
405    XW_RSYM(xW, handle, handle2, XvMCRenderSurface,);
406    XW_RSYM(xW, handle, handle2, XvMCSyncSubpicture,);
407    XW_RSYM(xW, handle, handle2, XvMCFlushSubpicture,);
408    XW_RSYM(xW, handle, handle2, XvMCGetSubpictureStatus,);
409    XW_RSYM(xW, handle, handle2, XvMCCreateBlocks,);
410    XW_RSYM(xW, handle, handle2, XvMCDestroyBlocks,);
411    XW_RSYM(xW, handle, handle2, XvMCCreateMacroBlocks,);
412    XW_RSYM(xW, handle, handle2, XvMCDestroyMacroBlocks,);
413    XW_RSYM(xW, handle, handle2, XvMCQueryAttributes,);
414    XW_RSYM(xW, handle, handle2, XvMCSetAttribute,);
415    XW_RSYM(xW, handle, handle2, XvMCGetAttribute,);
416    xW.initialised = 1;
417    XW_RSYM2(xW, handle, handle2, XvMCBeginSurface);
418    XW_RSYM(xW, handle, handle2, XvMCLoadQMatrix,);
419    XW_RSYM(xW, handle, handle2, XvMCPutSlice,);
420    XW_RSYM(xW, handle, handle2, XvMCPutSlice2,);
421    xW.vldextension = 1;
422}
423
424Bool
425XvMCQueryExtension(Display *display, int *eventBase, int *errBase)
426{
427    if (!wrapperPreInit)
428        preInitW(display);
429    if (!xW.preInitialised)
430        return 0;
431    return (*xW.XvMCQueryExtension) (display, eventBase, errBase);
432}
433
434Status
435XvMCQueryVersion(Display *display, int *major_versionp, int *minor_versionp)
436{
437    if (!wrapperPreInit)
438        preInitW(display);
439    if (!xW.preInitialised)
440        return 0;
441    return (*xW.XvMCQueryVersion) (display, major_versionp, minor_versionp);
442}
443
444XvMCSurfaceInfo *
445XvMCListSurfaceTypes(Display *dpy, XvPortID port, int *num)
446{
447    if (!wrapperInit)
448        initW(dpy, port);
449    if (!xW.initialised)
450        return NULL;
451    return (*xW.XvMCListSurfaceTypes) (dpy, port, num);
452}
453
454Status
455XvMCCreateContext(Display *display,
456                  XvPortID port,
457                  int surface_type_id,
458                  int width,
459                  int height,
460                  int flags,
461                  XvMCContext *context)
462{
463    if (!wrapperInit)
464        initW(display, port);
465    if (!xW.initialised)
466        return BadValue;
467    return (*xW.XvMCCreateContext) (display, port, surface_type_id,
468                                    width, height, flags, context);
469}
470
471Status
472XvMCDestroyContext(Display *display, XvMCContext *context)
473{
474    if (!xW.initialised)
475        return BadValue;
476    return (*xW.XvMCDestroyContext) (display, context);
477}
478
479Status
480XvMCCreateSurface(Display *display,
481                  XvMCContext *context,
482                  XvMCSurface *surface)
483{
484    if (!xW.initialised)
485        return BadValue;
486    return (*xW.XvMCCreateSurface) (display, context, surface);
487}
488
489Status
490XvMCDestroySurface(Display *display, XvMCSurface *surface)
491{
492    if (!xW.initialised)
493        return BadValue;
494    return (*xW.XvMCDestroySurface) (display, surface);
495}
496
497XvImageFormatValues *
498XvMCListSubpictureTypes(Display *display,
499                        XvPortID port,
500                        int surface_type_id,
501                        int *count_return)
502{
503    if (!xW.initialised)
504        return NULL;
505    return (*xW.XvMCListSubpictureTypes) (display, port, surface_type_id,
506                                          count_return);
507}
508
509Status
510XvMCPutSurface(Display *display,
511               XvMCSurface * surface,
512               Drawable draw,
513               short srcx,
514               short srcy,
515               unsigned short srcw,
516               unsigned short srch,
517               short destx,
518               short desty,
519               unsigned short destw,
520               unsigned short desth,
521               int flags)
522{
523    if (!xW.initialised)
524        return BadValue;
525    return (*xW.XvMCPutSurface) (display, surface, draw, srcx, srcy, srcw, srch,
526                                 destx, desty, destw, desth, flags);
527}
528
529Status
530XvMCHideSurface(Display *display, XvMCSurface *surface)
531{
532    if (!xW.initialised)
533        return BadValue;
534    return (*xW.XvMCHideSurface) (display, surface);
535}
536
537Status
538XvMCCreateSubpicture(Display *display,
539                     XvMCContext *context,
540                     XvMCSubpicture *subpicture,
541                     unsigned short width,
542                     unsigned short height,
543                     int xvimage_id)
544{
545    if (!xW.initialised)
546        return BadValue;
547    return (*xW.XvMCCreateSubpicture) (display, context, subpicture, width,
548                                       height, xvimage_id);
549}
550
551Status
552XvMCClearSubpicture(Display *display,
553                    XvMCSubpicture *subpicture,
554                    short x,
555                    short y,
556                    unsigned short width,
557                    unsigned short height,
558                    unsigned int color)
559{
560    if (!xW.initialised)
561        return BadValue;
562    return (*xW.XvMCClearSubpicture) (display, subpicture, x, y, width, height,
563                                      color);
564}
565
566Status
567XvMCCompositeSubpicture(Display *display,
568                        XvMCSubpicture *subpicture,
569                        XvImage *image,
570                        short srcx,
571                        short srcy,
572                        unsigned short width,
573                        unsigned short height,
574                        short dstx,
575                        short dsty)
576{
577    if (!xW.initialised)
578        return BadValue;
579    return (*xW.XvMCCompositeSubpicture) (display, subpicture, image, srcx,
580                                          srcy, width, height, dstx, dsty);
581}
582
583Status
584XvMCDestroySubpicture(Display *display, XvMCSubpicture *subpicture)
585{
586    if (!xW.initialised)
587        return BadValue;
588    return (*xW.XvMCDestroySubpicture) (display, subpicture);
589}
590
591Status
592XvMCSetSubpicturePalette(Display *display,
593                         XvMCSubpicture *subpicture,
594                         unsigned char *palette)
595{
596    if (!xW.initialised)
597        return BadValue;
598    return (*xW.XvMCSetSubpicturePalette) (display, subpicture, palette);
599}
600
601Status
602XvMCBlendSubpicture(Display *display,
603                    XvMCSurface *target_surface,
604                    XvMCSubpicture *subpicture,
605                    short subx,
606                    short suby,
607                    unsigned short subw,
608                    unsigned short subh,
609                    short surfx,
610                    short surfy,
611                    unsigned short surfw,
612                    unsigned short surfh)
613{
614    if (!xW.initialised)
615        return BadValue;
616    return (*xW.XvMCBlendSubpicture) (display, target_surface, subpicture,
617                                      subx, suby, subw, subh, surfx, surfy,
618                                      surfw, surfh);
619}
620
621Status
622XvMCBlendSubpicture2(Display *display,
623                     XvMCSurface *source_surface,
624                     XvMCSurface *target_surface,
625                     XvMCSubpicture *subpicture,
626                     short subx,
627                     short suby,
628                     unsigned short subw,
629                     unsigned short subh,
630                     short surfx,
631                     short surfy,
632                     unsigned short surfw,
633                     unsigned short surfh)
634{
635    if (!xW.initialised)
636        return BadValue;
637    return (*xW.XvMCBlendSubpicture2) (display, source_surface, target_surface,
638                                       subpicture, subx, suby, subw, subh,
639                                       surfx, surfy, surfw, surfh);
640}
641
642Status
643XvMCSyncSurface(Display *display, XvMCSurface *surface)
644{
645    if (!xW.initialised)
646        return BadValue;
647    return (*xW.XvMCSyncSurface) (display, surface);
648}
649
650Status
651XvMCFlushSurface(Display *display, XvMCSurface *surface)
652{
653    if (!xW.initialised)
654        return BadValue;
655    return (*xW.XvMCFlushSurface) (display, surface);
656}
657
658Status
659XvMCGetSurfaceStatus(Display *display, XvMCSurface *surface, int *stat)
660{
661    if (!xW.initialised)
662        return BadValue;
663    return (*xW.XvMCGetSurfaceStatus) (display, surface, stat);
664}
665
666Status
667XvMCRenderSurface(Display *display,
668                  XvMCContext *context,
669                  unsigned int picture_structure,
670                  XvMCSurface *target_surface,
671                  XvMCSurface *past_surface,
672                  XvMCSurface *future_surface,
673                  unsigned int flags,
674                  unsigned int num_macroblocks,
675                  unsigned int first_macroblock,
676                  XvMCMacroBlockArray *macroblock_array,
677                  XvMCBlockArray *blocks)
678{
679    if (!xW.initialised)
680        return BadValue;
681    return (*xW.XvMCRenderSurface) (display, context, picture_structure,
682                                    target_surface, past_surface,
683                                    future_surface, flags, num_macroblocks,
684                                    first_macroblock, macroblock_array, blocks);
685}
686
687Status
688XvMCSyncSubpicture(Display *display, XvMCSubpicture *subpicture)
689{
690    if (!xW.initialised)
691        return BadValue;
692    return (*xW.XvMCSyncSubpicture) (display, subpicture);
693}
694
695Status
696XvMCFlushSubpicture(Display *display, XvMCSubpicture *subpicture)
697{
698    if (!xW.initialised)
699        return BadValue;
700    return (*xW.XvMCFlushSubpicture) (display, subpicture);
701}
702
703Status
704XvMCGetSubpictureStatus(Display *display, XvMCSubpicture *subpic, int *stat)
705{
706    if (!xW.initialised)
707        return BadValue;
708    return (*xW.XvMCGetSubpictureStatus) (display, subpic, stat);
709}
710
711Status
712XvMCCreateBlocks(Display *display,
713                 XvMCContext *context,
714                 unsigned int num_blocks,
715                 XvMCBlockArray *block)
716{
717    if (!xW.initialised)
718        return BadValue;
719    return (*xW.XvMCCreateBlocks) (display, context, num_blocks, block);
720}
721
722Status
723XvMCDestroyBlocks(Display *display, XvMCBlockArray *block)
724{
725    if (!xW.initialised)
726        return BadValue;
727    return (*xW.XvMCDestroyBlocks) (display, block);
728}
729
730Status
731XvMCCreateMacroBlocks(Display *display,
732                      XvMCContext *context,
733                      unsigned int num_blocks,
734                      XvMCMacroBlockArray *blocks)
735{
736    if (!xW.initialised)
737        return BadValue;
738    return (*xW.XvMCCreateMacroBlocks) (display, context, num_blocks, blocks);
739}
740
741Status
742XvMCDestroyMacroBlocks(Display *display,
743                       XvMCMacroBlockArray *block)
744{
745    if (!xW.initialised)
746        return BadValue;
747    return (*xW.XvMCDestroyMacroBlocks) (display, block);
748}
749
750XvAttribute *
751XvMCQueryAttributes(Display *display,
752                    XvMCContext *context,
753                    int *number)
754{
755    if (!xW.initialised)
756        return NULL;
757    return (*xW.XvMCQueryAttributes) (display, context, number);
758}
759
760Status
761XvMCSetAttribute(Display *display,
762                 XvMCContext *context,
763                 Atom attribute,
764                 int value)
765{
766    if (!xW.initialised)
767        return BadValue;
768    return (*xW.XvMCSetAttribute) (display, context, attribute, value);
769}
770
771Status
772XvMCGetAttribute(Display *display,
773                 XvMCContext *context,
774                 Atom attribute,
775                 int *value)
776{
777    if (!xW.initialised)
778        return BadValue;
779    return (*xW.XvMCGetAttribute) (display, context, attribute, value);
780}
781
782Status
783XvMCBeginSurface(Display *display,
784                 XvMCContext *context,
785                 XvMCSurface *target_surface,
786                 XvMCSurface *past_surface,
787                 XvMCSurface *future_surface,
788                 const XvMCMpegControl *control)
789{
790    if (!xW.vldextension)
791        return BadValue;
792    return (*xW.XvMCBeginSurface) (display, context, target_surface,
793                                   past_surface, future_surface, control);
794}
795
796Status
797XvMCLoadQMatrix(Display *display, XvMCContext *context,
798                const XvMCQMatrix *qmx)
799{
800    if (!xW.vldextension)
801        return BadValue;
802    return (*xW.XvMCLoadQMatrix) (display, context, qmx);
803}
804
805Status
806XvMCPutSlice(Display *display, XvMCContext *context, char *slice, int nBytes)
807{
808    if (!xW.vldextension)
809        return BadValue;
810    return (*xW.XvMCPutSlice) (display, context, slice, nBytes);
811}
812
813Status
814XvMCPutSlice2(Display *display, XvMCContext *context,
815              char *slice, int nBytes, int sliceCode)
816{
817    if (!xW.vldextension)
818        return BadValue;
819    return (*xW.XvMCPutSlice2) (display, context, slice, nBytes, sliceCode);
820}
821