XvMC.c revision 4e5182b7
16f03b1f6Smrg#ifdef HAVE_CONFIG_H
26f03b1f6Smrg#include <config.h>
36f03b1f6Smrg#endif
46f03b1f6Smrg#include <stdio.h>
56f03b1f6Smrg#include "XvMClibint.h"
642941e3bSmrg#ifdef HAVE_SHMAT
76f03b1f6Smrg#ifndef Lynx
86f03b1f6Smrg#include <sys/ipc.h>
96f03b1f6Smrg#include <sys/shm.h>
106f03b1f6Smrg#else
116f03b1f6Smrg#include <ipc.h>
126f03b1f6Smrg#include <shm.h>
136f03b1f6Smrg#endif /* Lynx */
1442941e3bSmrg#endif /* HAVE_SHMAT */
156f03b1f6Smrg#include <unistd.h>
166f03b1f6Smrg#include <sys/time.h>
176f03b1f6Smrg#include <X11/extensions/Xext.h>
186f03b1f6Smrg#include <X11/extensions/extutil.h>
19190694daSmrg#include <limits.h>
206f03b1f6Smrg
216f03b1f6Smrgstatic XExtensionInfo _xvmc_info_data;
226f03b1f6Smrgstatic XExtensionInfo *xvmc_info = &_xvmc_info_data;
2342941e3bSmrgstatic const char *xvmc_extension_name = XvMCName;
246f03b1f6Smrg
2542941e3bSmrgstatic const char *xvmc_error_list[] =
266f03b1f6Smrg{
276f03b1f6Smrg   "BadContext",
286f03b1f6Smrg   "BadSurface",
296f03b1f6Smrg   "BadSubpicture"
306f03b1f6Smrg};
316f03b1f6Smrg
326f03b1f6Smrgstatic XEXT_GENERATE_CLOSE_DISPLAY (xvmc_close_display, xvmc_info)
336f03b1f6Smrg
346f03b1f6Smrg
356f03b1f6Smrgstatic XEXT_GENERATE_ERROR_STRING (xvmc_error_string, xvmc_extension_name,
366f03b1f6Smrg                                   XvMCNumErrors, xvmc_error_list)
376f03b1f6Smrg
386f03b1f6Smrg
396f03b1f6Smrgstatic XExtensionHooks xvmc_extension_hooks = {
406f03b1f6Smrg    NULL,                               /* create_gc */
416f03b1f6Smrg    NULL,                               /* copy_gc */
426f03b1f6Smrg    NULL,                               /* flush_gc */
436f03b1f6Smrg    NULL,                               /* free_gc */
446f03b1f6Smrg    NULL,                               /* create_font */
456f03b1f6Smrg    NULL,                               /* free_font */
466f03b1f6Smrg    xvmc_close_display,                 /* close_display */
476f03b1f6Smrg    NULL,                               /* wire_to_event */
486f03b1f6Smrg    NULL,                               /* event_to_wire */
496f03b1f6Smrg    NULL,                               /* error */
506f03b1f6Smrg    xvmc_error_string                   /* error_string */
516f03b1f6Smrg};
526f03b1f6Smrg
536f03b1f6Smrgstatic XEXT_GENERATE_FIND_DISPLAY (xvmc_find_display, xvmc_info,
546f03b1f6Smrg                                   xvmc_extension_name,
556f03b1f6Smrg                                   &xvmc_extension_hooks,
566f03b1f6Smrg                                   XvMCNumEvents, NULL)
576f03b1f6Smrg
586f03b1f6SmrgBool XvMCQueryExtension (Display *dpy, int *event_basep, int *error_basep)
596f03b1f6Smrg{
606f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
616f03b1f6Smrg
626f03b1f6Smrg    if (XextHasExtension(info)) {
636f03b1f6Smrg        *event_basep = info->codes->first_event;
646f03b1f6Smrg        *error_basep = info->codes->first_error;
656f03b1f6Smrg        return True;
666f03b1f6Smrg    } else {
676f03b1f6Smrg        return False;
686f03b1f6Smrg    }
696f03b1f6Smrg}
706f03b1f6Smrg
716f03b1f6SmrgStatus XvMCQueryVersion (Display *dpy, int *major, int *minor)
726f03b1f6Smrg{
736f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
746f03b1f6Smrg    xvmcQueryVersionReply rep;
756f03b1f6Smrg    xvmcQueryVersionReq  *req;
766f03b1f6Smrg
776f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
786f03b1f6Smrg
796f03b1f6Smrg    LockDisplay (dpy);
806f03b1f6Smrg    XvMCGetReq (QueryVersion, req);
816f03b1f6Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
826f03b1f6Smrg        UnlockDisplay (dpy);
836f03b1f6Smrg        SyncHandle ();
846f03b1f6Smrg        return BadImplementation;
856f03b1f6Smrg    }
866f03b1f6Smrg    *major = rep.major;
876f03b1f6Smrg    *minor = rep.minor;
886f03b1f6Smrg    UnlockDisplay (dpy);
896f03b1f6Smrg    SyncHandle ();
906f03b1f6Smrg    return Success;
916f03b1f6Smrg}
926f03b1f6Smrg
936f03b1f6Smrg
946f03b1f6SmrgXvMCSurfaceInfo * XvMCListSurfaceTypes(Display *dpy, XvPortID port, int *num)
956f03b1f6Smrg{
966f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
976f03b1f6Smrg    xvmcListSurfaceTypesReply rep;
986f03b1f6Smrg    xvmcListSurfaceTypesReq  *req;
996f03b1f6Smrg    XvMCSurfaceInfo *surface_info = NULL;
1006f03b1f6Smrg
1016f03b1f6Smrg    *num = 0;
1026f03b1f6Smrg
1036f03b1f6Smrg    XvMCCheckExtension (dpy, info, NULL);
10442941e3bSmrg
1056f03b1f6Smrg    LockDisplay (dpy);
1066f03b1f6Smrg    XvMCGetReq (ListSurfaceTypes, req);
1076f03b1f6Smrg    req->port = port;
1086f03b1f6Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
1096f03b1f6Smrg        UnlockDisplay (dpy);
1106f03b1f6Smrg        SyncHandle ();
1116f03b1f6Smrg        return NULL;
1126f03b1f6Smrg    }
1136f03b1f6Smrg
1146f03b1f6Smrg    if(rep.num > 0) {
115190694daSmrg        if (rep.num < (INT_MAX / sizeof(XvMCSurfaceInfo)))
116190694daSmrg            surface_info = Xmalloc(rep.num * sizeof(XvMCSurfaceInfo));
1176f03b1f6Smrg
1186f03b1f6Smrg        if(surface_info) {
1196f03b1f6Smrg	    xvmcSurfaceInfo sinfo;
1207448d6e9Smrg	    CARD32 i;
1216f03b1f6Smrg
1226f03b1f6Smrg	    *num = rep.num;
1236f03b1f6Smrg
1246f03b1f6Smrg	    for(i = 0; i < rep.num; i++) {
1256f03b1f6Smrg		_XRead(dpy, (char*)&sinfo, sizeof(xvmcSurfaceInfo));
1266f03b1f6Smrg	       surface_info[i].surface_type_id = sinfo.surface_type_id;
1276f03b1f6Smrg	       surface_info[i].chroma_format = sinfo.chroma_format;
1286f03b1f6Smrg	       surface_info[i].max_width = sinfo.max_width;
1296f03b1f6Smrg	       surface_info[i].max_height = sinfo.max_height;
13042941e3bSmrg	       surface_info[i].subpicture_max_width =
1316f03b1f6Smrg					sinfo.subpicture_max_width;
13242941e3bSmrg	       surface_info[i].subpicture_max_height =
1336f03b1f6Smrg					sinfo.subpicture_max_height;
1346f03b1f6Smrg	       surface_info[i].mc_type = sinfo.mc_type;
1356f03b1f6Smrg	       surface_info[i].flags = sinfo.flags;
1366f03b1f6Smrg	    }
1376f03b1f6Smrg	} else
138cc1b55f9Smrg	   _XEatDataWords(dpy, rep.length);
1396f03b1f6Smrg    }
1406f03b1f6Smrg
1416f03b1f6Smrg    UnlockDisplay (dpy);
1426f03b1f6Smrg    SyncHandle ();
1436f03b1f6Smrg    return surface_info;
1446f03b1f6Smrg}
1456f03b1f6Smrg
1466f03b1f6Smrg
1476f03b1f6SmrgXvImageFormatValues * XvMCListSubpictureTypes (
1486f03b1f6Smrg  Display * dpy,
1496f03b1f6Smrg  XvPortID port,
1506f03b1f6Smrg  int surface_type_id,
1516f03b1f6Smrg  int *count_return
1526f03b1f6Smrg)
1536f03b1f6Smrg{
1546f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
1556f03b1f6Smrg    xvmcListSubpictureTypesReply rep;
1566f03b1f6Smrg    xvmcListSubpictureTypesReq  *req;
1576f03b1f6Smrg    XvImageFormatValues *ret = NULL;
1586f03b1f6Smrg
1596f03b1f6Smrg
1606f03b1f6Smrg    *count_return = 0;
1616f03b1f6Smrg
1626f03b1f6Smrg    XvMCCheckExtension (dpy, info, NULL);
1636f03b1f6Smrg
1646f03b1f6Smrg
1656f03b1f6Smrg    LockDisplay (dpy);
1666f03b1f6Smrg    XvMCGetReq (ListSubpictureTypes, req);
1676f03b1f6Smrg    req->port = port;
1686f03b1f6Smrg    req->surface_type_id = surface_type_id;
1696f03b1f6Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
1706f03b1f6Smrg        UnlockDisplay (dpy);
1716f03b1f6Smrg        SyncHandle ();
1726f03b1f6Smrg        return NULL;
1736f03b1f6Smrg    }
1746f03b1f6Smrg
1756f03b1f6Smrg    if(rep.num > 0) {
176190694daSmrg        if (rep.num < (INT_MAX / sizeof(XvImageFormatValues)))
177190694daSmrg            ret = Xmalloc(rep.num * sizeof(XvImageFormatValues));
1786f03b1f6Smrg
1796f03b1f6Smrg        if(ret) {
1806f03b1f6Smrg            xvImageFormatInfo Info;
1817448d6e9Smrg            CARD32 i;
1826f03b1f6Smrg
1836f03b1f6Smrg            *count_return = rep.num;
1846f03b1f6Smrg
1856f03b1f6Smrg            for(i = 0; i < rep.num; i++) {
1866f03b1f6Smrg              _XRead(dpy, (char*)(&Info), sz_xvImageFormatInfo);
18742941e3bSmrg              ret[i].id = Info.id;
18842941e3bSmrg              ret[i].type = Info.type;
18942941e3bSmrg              ret[i].byte_order = Info.byte_order;
1906f03b1f6Smrg              memcpy(&(ret[i].guid[0]), &(Info.guid[0]), 16);
19142941e3bSmrg              ret[i].bits_per_pixel = Info.bpp;
19242941e3bSmrg              ret[i].format = Info.format;
19342941e3bSmrg              ret[i].num_planes = Info.num_planes;
19442941e3bSmrg              ret[i].depth = Info.depth;
19542941e3bSmrg              ret[i].red_mask = Info.red_mask;
19642941e3bSmrg              ret[i].green_mask = Info.green_mask;
19742941e3bSmrg              ret[i].blue_mask = Info.blue_mask;
19842941e3bSmrg              ret[i].y_sample_bits = Info.y_sample_bits;
19942941e3bSmrg              ret[i].u_sample_bits = Info.u_sample_bits;
2006f03b1f6Smrg              ret[i].v_sample_bits = Info.v_sample_bits;
2016f03b1f6Smrg              ret[i].horz_y_period = Info.horz_y_period;
2026f03b1f6Smrg              ret[i].horz_u_period = Info.horz_u_period;
2036f03b1f6Smrg              ret[i].horz_v_period = Info.horz_v_period;
2046f03b1f6Smrg              ret[i].vert_y_period = Info.vert_y_period;
2056f03b1f6Smrg              ret[i].vert_u_period = Info.vert_u_period;
2066f03b1f6Smrg              ret[i].vert_v_period = Info.vert_v_period;
2076f03b1f6Smrg              memcpy(&(ret[i].component_order[0]), &(Info.comp_order[0]), 32);
2086f03b1f6Smrg              ret[i].scanline_order = Info.scanline_order;
2096f03b1f6Smrg            }
2106f03b1f6Smrg        } else
211cc1b55f9Smrg	   _XEatDataWords(dpy, rep.length);
2126f03b1f6Smrg    }
2136f03b1f6Smrg
2146f03b1f6Smrg    UnlockDisplay (dpy);
2156f03b1f6Smrg    SyncHandle ();
21642941e3bSmrg    return ret;
2176f03b1f6Smrg}
2186f03b1f6Smrg
2196f03b1f6Smrg
22042941e3bSmrg/******************************************************************
2216f03b1f6Smrg   These are intended as a protocol interface to be used by direct
2226f03b1f6Smrg   rendering libraries.  They are not intended to be client viewable
2236f03b1f6Smrg   functions.  These will stay in place until we have a mechanism in
2246f03b1f6Smrg   place similar to that of OpenGL with an libXvMCcore library.
22542941e3bSmrg*******************************************************************/
22642941e3bSmrg
22742941e3bSmrg/*
2286f03b1f6Smrg   _xvmc_create_context -
2296f03b1f6Smrg
2306f03b1f6Smrg   Pass in the context with the surface_type_id, width, height,
2316f03b1f6Smrg   port and flags filled out.  This function will fill out the
2326f03b1f6Smrg   context_id and update the width, height and flags field.
2336f03b1f6Smrg   The server may return implementation-specific information
2346f03b1f6Smrg   back in the priv_data.  The size of that information will
2356f03b1f6Smrg   an array of priv_count CARD32s.  This data is allocated by
2366f03b1f6Smrg   this function.  If returned, the caller is responsible for
2376f03b1f6Smrg   freeing it!  Generally, such information is only returned if
23842941e3bSmrg   an XVMC_DIRECT context was specified.
2396f03b1f6Smrg*/
2406f03b1f6Smrg
2416f03b1f6Smrg
2426f03b1f6SmrgStatus _xvmc_create_context (
2436f03b1f6Smrg    Display *dpy,
2446f03b1f6Smrg    XvMCContext *context,
2456f03b1f6Smrg    int *priv_count,
2466f03b1f6Smrg    CARD32 **priv_data
2476f03b1f6Smrg)
2486f03b1f6Smrg{
2496f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
2506f03b1f6Smrg    xvmcCreateContextReply rep;
2516f03b1f6Smrg    xvmcCreateContextReq  *req;
2526f03b1f6Smrg
2536f03b1f6Smrg    *priv_count = 0;
2546f03b1f6Smrg    *priv_data = NULL;
2556f03b1f6Smrg
2566f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
2576f03b1f6Smrg
2586f03b1f6Smrg    LockDisplay (dpy);
2596f03b1f6Smrg    XvMCGetReq (CreateContext, req);
2606f03b1f6Smrg    context->context_id = XAllocID(dpy);
2616f03b1f6Smrg    req->context_id = context->context_id;
2626f03b1f6Smrg    req->port = context->port;
2636f03b1f6Smrg    req->surface_type_id = context->surface_type_id;
2646f03b1f6Smrg    req->width = context->width;
2656f03b1f6Smrg    req->height = context->height;
2666f03b1f6Smrg    req->flags = context->flags;
2676f03b1f6Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
2686f03b1f6Smrg        UnlockDisplay (dpy);
2696f03b1f6Smrg        SyncHandle ();
2706f03b1f6Smrg        return BadImplementation;
2716f03b1f6Smrg    }
2726f03b1f6Smrg    context->width = rep.width_actual;
2736f03b1f6Smrg    context->height = rep.height_actual;
2746f03b1f6Smrg    context->flags = rep.flags_return;
2756f03b1f6Smrg
2766f03b1f6Smrg    if(rep.length) {
277cc1b55f9Smrg	if (rep.length < (INT_MAX >> 2))
278cc1b55f9Smrg	    *priv_data = Xmalloc(rep.length << 2);
2796f03b1f6Smrg	if(*priv_data) {
2806f03b1f6Smrg            _XRead(dpy, (char*)(*priv_data), rep.length << 2);
2816f03b1f6Smrg	    *priv_count = rep.length;
2826f03b1f6Smrg	} else
283cc1b55f9Smrg	    _XEatDataWords(dpy, rep.length);
2846f03b1f6Smrg    }
2856f03b1f6Smrg
2866f03b1f6Smrg    UnlockDisplay (dpy);
2876f03b1f6Smrg    SyncHandle ();
2886f03b1f6Smrg    return Success;
2896f03b1f6Smrg}
2906f03b1f6Smrg
2916f03b1f6SmrgStatus _xvmc_destroy_context (
2926f03b1f6Smrg    Display *dpy,
2936f03b1f6Smrg    XvMCContext *context
2946f03b1f6Smrg)
2956f03b1f6Smrg{
2966f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
2976f03b1f6Smrg    xvmcDestroyContextReq  *req;
2986f03b1f6Smrg
2996f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
3006f03b1f6Smrg
3016f03b1f6Smrg    LockDisplay (dpy);
3026f03b1f6Smrg    XvMCGetReq (DestroyContext, req);
3036f03b1f6Smrg    req->context_id = context->context_id;
3046f03b1f6Smrg    UnlockDisplay (dpy);
3056f03b1f6Smrg    SyncHandle ();
3066f03b1f6Smrg    return Success;
3076f03b1f6Smrg}
3086f03b1f6Smrg
3096f03b1f6Smrg
3106f03b1f6Smrg/*
3116f03b1f6Smrg   _xvmc_create_surface -
3126f03b1f6Smrg
3136f03b1f6Smrg   Pass the context and this function will fill out all the
31442941e3bSmrg   information in the surface.
3156f03b1f6Smrg   The server may return implementation-specific information
3166f03b1f6Smrg   back in the priv_data.  The size of that information will
3176f03b1f6Smrg   an array of priv_count CARD32s.  This data is allocated by
3186f03b1f6Smrg   this function.  If returned, the caller is responsible for
3196f03b1f6Smrg   freeing it!  Generally, such information is returned only if
3206f03b1f6Smrg   the context was a direct context.
32142941e3bSmrg
3226f03b1f6Smrg*/
3236f03b1f6Smrg
3246f03b1f6SmrgStatus _xvmc_create_surface (
3256f03b1f6Smrg    Display *dpy,
3266f03b1f6Smrg    XvMCContext *context,
3276f03b1f6Smrg    XvMCSurface *surface,
3286f03b1f6Smrg    int *priv_count,
3296f03b1f6Smrg    CARD32 **priv_data
3306f03b1f6Smrg)
3316f03b1f6Smrg{
3326f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
3336f03b1f6Smrg    xvmcCreateSurfaceReply rep;
3346f03b1f6Smrg    xvmcCreateSurfaceReq  *req;
3356f03b1f6Smrg
3366f03b1f6Smrg    *priv_count = 0;
3376f03b1f6Smrg    *priv_data = NULL;
3386f03b1f6Smrg
3396f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
3406f03b1f6Smrg
3416f03b1f6Smrg    LockDisplay (dpy);
3426f03b1f6Smrg    XvMCGetReq (CreateSurface, req);
3436f03b1f6Smrg
3446f03b1f6Smrg    surface->surface_id = XAllocID(dpy);
3456f03b1f6Smrg    surface->context_id = context->context_id;
3466f03b1f6Smrg    surface->surface_type_id = context->surface_type_id;
3476f03b1f6Smrg    surface->width = context->width;
3486f03b1f6Smrg    surface->height = context->height;
3496f03b1f6Smrg
3506f03b1f6Smrg    req->surface_id = surface->surface_id;
3516f03b1f6Smrg    req->context_id = surface->context_id;
3526f03b1f6Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
3536f03b1f6Smrg        UnlockDisplay (dpy);
3546f03b1f6Smrg        SyncHandle ();
3556f03b1f6Smrg        return BadImplementation;
3566f03b1f6Smrg    }
3576f03b1f6Smrg
3586f03b1f6Smrg    if(rep.length) {
359cc1b55f9Smrg        if (rep.length < (INT_MAX >> 2))
360cc1b55f9Smrg            *priv_data = Xmalloc(rep.length << 2);
3616f03b1f6Smrg        if(*priv_data) {
3626f03b1f6Smrg            _XRead(dpy, (char*)(*priv_data), rep.length << 2);
3636f03b1f6Smrg            *priv_count = rep.length;
3646f03b1f6Smrg        } else
365cc1b55f9Smrg            _XEatDataWords(dpy, rep.length);
3666f03b1f6Smrg    }
3676f03b1f6Smrg
3686f03b1f6Smrg    UnlockDisplay (dpy);
3696f03b1f6Smrg    SyncHandle ();
3706f03b1f6Smrg    return Success;
3716f03b1f6Smrg}
3726f03b1f6Smrg
3736f03b1f6SmrgStatus _xvmc_destroy_surface (
3746f03b1f6Smrg    Display *dpy,
3756f03b1f6Smrg    XvMCSurface *surface
3766f03b1f6Smrg)
3776f03b1f6Smrg{
3786f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
3796f03b1f6Smrg    xvmcDestroySurfaceReq  *req;
3806f03b1f6Smrg
3816f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
3826f03b1f6Smrg
3836f03b1f6Smrg    LockDisplay (dpy);
3846f03b1f6Smrg    XvMCGetReq (DestroySurface, req);
3856f03b1f6Smrg    req->surface_id = surface->surface_id;
3866f03b1f6Smrg    UnlockDisplay (dpy);
3876f03b1f6Smrg    SyncHandle ();
3886f03b1f6Smrg    return Success;
3896f03b1f6Smrg}
3906f03b1f6Smrg
3916f03b1f6Smrg/*
3926f03b1f6Smrg   _xvmc_create_subpicture -
3936f03b1f6Smrg
3946f03b1f6Smrg   Pass the subpicture with the width, height and xvimage_id filled
3956f03b1f6Smrg   out and this function will fill out everything else in the
3966f03b1f6Smrg   subpicture as well as adjust the width and height if needed.
3976f03b1f6Smrg   The server may return implementation-specific information
3986f03b1f6Smrg   back in the priv_data.  The size of that information will
3996f03b1f6Smrg   an array of priv_count CARD32s.  This data is allocated by
4006f03b1f6Smrg   this function.  If returned, the caller is responsible for
4016f03b1f6Smrg   freeing it!  Generally, such information is returned only if
4026f03b1f6Smrg   the context was a direct context.
4036f03b1f6Smrg
4046f03b1f6Smrg*/
4056f03b1f6Smrg
4066f03b1f6SmrgStatus _xvmc_create_subpicture (
4076f03b1f6Smrg    Display *dpy,
4086f03b1f6Smrg    XvMCContext *context,
4096f03b1f6Smrg    XvMCSubpicture *subpicture,
4106f03b1f6Smrg    int *priv_count,
4116f03b1f6Smrg    CARD32 **priv_data
4126f03b1f6Smrg)
4136f03b1f6Smrg{
4146f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
4156f03b1f6Smrg    xvmcCreateSubpictureReply rep;
4166f03b1f6Smrg    xvmcCreateSubpictureReq  *req;
4176f03b1f6Smrg
4186f03b1f6Smrg    *priv_count = 0;
4196f03b1f6Smrg    *priv_data = NULL;
4206f03b1f6Smrg
4216f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
4226f03b1f6Smrg
4236f03b1f6Smrg    LockDisplay (dpy);
4246f03b1f6Smrg    XvMCGetReq (CreateSubpicture, req);
4256f03b1f6Smrg
4266f03b1f6Smrg    subpicture->subpicture_id = XAllocID(dpy);
4276f03b1f6Smrg    subpicture->context_id = context->context_id;
4286f03b1f6Smrg
4296f03b1f6Smrg    req->subpicture_id = subpicture->subpicture_id;
4306f03b1f6Smrg    req->context_id = subpicture->context_id;
4316f03b1f6Smrg    req->xvimage_id = subpicture->xvimage_id;
4326f03b1f6Smrg    req->width = subpicture->width;
4336f03b1f6Smrg    req->height = subpicture->height;
4346f03b1f6Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
4356f03b1f6Smrg        UnlockDisplay (dpy);
4366f03b1f6Smrg        SyncHandle ();
4376f03b1f6Smrg        return BadImplementation;
4386f03b1f6Smrg    }
4396f03b1f6Smrg
4406f03b1f6Smrg    subpicture->width = rep.width_actual;
4416f03b1f6Smrg    subpicture->height = rep.height_actual;
4426f03b1f6Smrg    subpicture->num_palette_entries = rep.num_palette_entries;
4436f03b1f6Smrg    subpicture->entry_bytes = rep.entry_bytes;
4446f03b1f6Smrg    subpicture->component_order[0] = rep.component_order[0];
4456f03b1f6Smrg    subpicture->component_order[1] = rep.component_order[1];
4466f03b1f6Smrg    subpicture->component_order[2] = rep.component_order[2];
4476f03b1f6Smrg    subpicture->component_order[3] = rep.component_order[3];
4486f03b1f6Smrg
4496f03b1f6Smrg    if(rep.length) {
450cc1b55f9Smrg        if (rep.length < (INT_MAX >> 2))
451cc1b55f9Smrg            *priv_data = Xmalloc(rep.length << 2);
4526f03b1f6Smrg        if(*priv_data) {
4536f03b1f6Smrg            _XRead(dpy, (char*)(*priv_data), rep.length << 2);
4546f03b1f6Smrg            *priv_count = rep.length;
4556f03b1f6Smrg        } else
456cc1b55f9Smrg            _XEatDataWords(dpy, rep.length);
4576f03b1f6Smrg    }
4586f03b1f6Smrg
4596f03b1f6Smrg    UnlockDisplay (dpy);
4606f03b1f6Smrg    SyncHandle ();
4616f03b1f6Smrg    return Success;
4626f03b1f6Smrg}
4636f03b1f6Smrg
4646f03b1f6SmrgStatus _xvmc_destroy_subpicture(
4656f03b1f6Smrg    Display *dpy,
4666f03b1f6Smrg    XvMCSubpicture *subpicture
4676f03b1f6Smrg)
4686f03b1f6Smrg{
4696f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
4706f03b1f6Smrg    xvmcDestroySubpictureReq  *req;
4716f03b1f6Smrg
4726f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
4736f03b1f6Smrg
4746f03b1f6Smrg    LockDisplay (dpy);
4756f03b1f6Smrg    XvMCGetReq (DestroySubpicture, req);
47642941e3bSmrg    req->subpicture_id = subpicture->subpicture_id;
4776f03b1f6Smrg    UnlockDisplay (dpy);
4786f03b1f6Smrg    SyncHandle ();
4796f03b1f6Smrg    return Success;
4806f03b1f6Smrg}
4816f03b1f6Smrg
4826f03b1f6SmrgStatus XvMCGetDRInfo(Display *dpy, XvPortID port,
48342941e3bSmrg		     char **name, char **busID,
48442941e3bSmrg		     int *major, int *minor,
4856f03b1f6Smrg		     int *patchLevel,
4866f03b1f6Smrg		     int *isLocal)
4876f03b1f6Smrg{
4886f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
4896f03b1f6Smrg    xvmcGetDRInfoReply rep;
4906f03b1f6Smrg    xvmcGetDRInfoReq  *req;
4916f03b1f6Smrg    CARD32 magic;
4926f03b1f6Smrg
49342941e3bSmrg#ifdef HAVE_SHMAT
4947448d6e9Smrg    int shmKey;
4956f03b1f6Smrg    volatile CARD32 *shMem;
4966f03b1f6Smrg    struct timezone here;
4976f03b1f6Smrg    struct timeval now;
4986f03b1f6Smrg    here.tz_minuteswest = 0;
4996f03b1f6Smrg    here.tz_dsttime = 0;
5006f03b1f6Smrg#endif
5016f03b1f6Smrg
502190694daSmrg    *name = NULL;
503190694daSmrg    *busID = NULL;
504190694daSmrg
5056f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
5066f03b1f6Smrg
5076f03b1f6Smrg    LockDisplay (dpy);
5086f03b1f6Smrg    XvMCGetReq (GetDRInfo, req);
5096f03b1f6Smrg
5106f03b1f6Smrg    req->port = port;
5116f03b1f6Smrg    magic = 0;
5126f03b1f6Smrg    req->magic = 0;
51342941e3bSmrg#ifdef HAVE_SHMAT
5147448d6e9Smrg    shmKey = shmget(IPC_PRIVATE, 1024, IPC_CREAT | 0600);
5157448d6e9Smrg    req->shmKey = (CARD32) shmKey;
5166f03b1f6Smrg
5176f03b1f6Smrg    /*
5186f03b1f6Smrg     * We fill a shared memory page with a repetitive pattern. If the
5196f03b1f6Smrg     * X server can read this pattern, we probably have a local connection.
5206f03b1f6Smrg     * Note that we can trigger the remote X server to read any shared
5216f03b1f6Smrg     * page on the remote machine, so we shouldn't be able to guess and verify
5224e5182b7Smrg     * any complicated data on those pages. That's the explanation of this
5236f03b1f6Smrg     * otherwise stupid-looking pattern algorithm.
5246f03b1f6Smrg     */
52542941e3bSmrg
5267448d6e9Smrg    if (shmKey >= 0) {
5277448d6e9Smrg	shMem = (CARD32 *) shmat(shmKey, NULL, 0);
5287448d6e9Smrg	shmctl(shmKey, IPC_RMID, NULL);
5297448d6e9Smrg	if (shMem != (void *) -1) {
5306f03b1f6Smrg
5316f03b1f6Smrg	    register volatile CARD32 *shMemC = shMem;
5326f03b1f6Smrg	    register int i;
5336f03b1f6Smrg
5346f03b1f6Smrg	    gettimeofday( &now, &here);
5356f03b1f6Smrg	    magic = now.tv_usec & 0x000FFFFF;
5366f03b1f6Smrg	    req->magic = magic;
5376f03b1f6Smrg	    i = 1024 / sizeof(CARD32);
5386f03b1f6Smrg	    while(i--) {
53942941e3bSmrg	        *shMemC++ = magic;
5406f03b1f6Smrg	        magic = ~magic;
5416f03b1f6Smrg	    }
5426f03b1f6Smrg	} else {
5436f03b1f6Smrg	    req->shmKey = -1;
5447448d6e9Smrg	    shmKey = -1;
5456f03b1f6Smrg	}
5466f03b1f6Smrg    }
5476f03b1f6Smrg#else
5486f03b1f6Smrg    req->shmKey = 0;
5496f03b1f6Smrg#endif
5506f03b1f6Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
5516f03b1f6Smrg        UnlockDisplay (dpy);
5526f03b1f6Smrg        SyncHandle ();
55342941e3bSmrg#ifdef HAVE_SHMAT
5547448d6e9Smrg	if (shmKey >= 0) {
5556f03b1f6Smrg	    shmdt( (const void *) shMem );
55642941e3bSmrg	}
5576f03b1f6Smrg#endif
5586f03b1f6Smrg        return -1;
5596f03b1f6Smrg    }
56042941e3bSmrg#ifdef HAVE_SHMAT
5617448d6e9Smrg    if (shmKey >= 0) {
5627448d6e9Smrg        shmdt( (const void *) shMem );
5637448d6e9Smrg    }
5646f03b1f6Smrg#endif
5656f03b1f6Smrg
5666f03b1f6Smrg    if (rep.length > 0) {
567190694daSmrg	unsigned long realSize = 0;
568190694daSmrg	char *tmpBuf = NULL;
569190694daSmrg
570cc1b55f9Smrg	if ((rep.length < (INT_MAX >> 2)) &&
571cc1b55f9Smrg	    /* protect against overflow in strncpy below */
572cc1b55f9Smrg	    (rep.nameLen + rep.busIDLen > rep.nameLen)) {
573190694daSmrg	    realSize = rep.length << 2;
574190694daSmrg	    if (realSize >= (rep.nameLen + rep.busIDLen)) {
575190694daSmrg		tmpBuf = Xmalloc(realSize);
576190694daSmrg		*name = Xmalloc(rep.nameLen);
577190694daSmrg		*busID = Xmalloc(rep.busIDLen);
57842941e3bSmrg	    }
5796f03b1f6Smrg	}
5806f03b1f6Smrg
5816f03b1f6Smrg	if (*name && *busID && tmpBuf) {
5826f03b1f6Smrg	    _XRead(dpy, tmpBuf, realSize);
5836f03b1f6Smrg	    strncpy(*name,tmpBuf,rep.nameLen);
584f1c62215Smrg	    (*name)[rep.nameLen == 0 ? 0 : rep.nameLen - 1] = '\0';
5856f03b1f6Smrg	    strncpy(*busID,tmpBuf+rep.nameLen,rep.busIDLen);
586f1c62215Smrg	    (*busID)[rep.busIDLen == 0 ? 0 : rep.busIDLen - 1] = '\0';
5876f03b1f6Smrg	    XFree(tmpBuf);
5886f03b1f6Smrg	} else {
589190694daSmrg	    XFree(*name);
590190694daSmrg	    *name = NULL;
591190694daSmrg	    XFree(*busID);
592cc1b55f9Smrg	    *busID = NULL;
593190694daSmrg	    XFree(tmpBuf);
5946f03b1f6Smrg
595cc1b55f9Smrg	    _XEatDataWords(dpy, rep.length);
5966f03b1f6Smrg	    UnlockDisplay (dpy);
5976f03b1f6Smrg	    SyncHandle ();
5986f03b1f6Smrg	    return -1;
5996f03b1f6Smrg
6006f03b1f6Smrg	}
6016f03b1f6Smrg    }
6026f03b1f6Smrg
6036f03b1f6Smrg    UnlockDisplay (dpy);
6046f03b1f6Smrg    SyncHandle ();
6056f03b1f6Smrg    *major = rep.major;
6066f03b1f6Smrg    *minor = rep.minor;
6076f03b1f6Smrg    *patchLevel = rep.patchLevel;
6087448d6e9Smrg#ifdef HAVE_SHMAT
6097448d6e9Smrg    if (shmKey >= 0)
6107448d6e9Smrg        *isLocal = rep.isLocal;
6117448d6e9Smrg    else
6127448d6e9Smrg#endif
6137448d6e9Smrg        *isLocal = 1;
6146f03b1f6Smrg    return (rep.length > 0) ? Success : BadImplementation;
6156f03b1f6Smrg}
6166f03b1f6Smrg
617