XvMC.c revision 190694da
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;
1206f03b1f6Smrg	    int 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
1386f03b1f6Smrg	   _XEatData(dpy, rep.length << 2);
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;
1816f03b1f6Smrg            int 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
2116f03b1f6Smrg	   _XEatData(dpy, rep.length << 2);
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) {
2776f03b1f6Smrg	*priv_data = Xmalloc(rep.length << 2);
2786f03b1f6Smrg	if(*priv_data) {
2796f03b1f6Smrg            _XRead(dpy, (char*)(*priv_data), rep.length << 2);
2806f03b1f6Smrg	    *priv_count = rep.length;
2816f03b1f6Smrg	} else
2826f03b1f6Smrg	    _XEatData(dpy, rep.length << 2);
2836f03b1f6Smrg    }
2846f03b1f6Smrg
2856f03b1f6Smrg    UnlockDisplay (dpy);
2866f03b1f6Smrg    SyncHandle ();
2876f03b1f6Smrg    return Success;
2886f03b1f6Smrg}
2896f03b1f6Smrg
2906f03b1f6SmrgStatus _xvmc_destroy_context (
2916f03b1f6Smrg    Display *dpy,
2926f03b1f6Smrg    XvMCContext *context
2936f03b1f6Smrg)
2946f03b1f6Smrg{
2956f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
2966f03b1f6Smrg    xvmcDestroyContextReq  *req;
2976f03b1f6Smrg
2986f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
2996f03b1f6Smrg
3006f03b1f6Smrg    LockDisplay (dpy);
3016f03b1f6Smrg    XvMCGetReq (DestroyContext, req);
3026f03b1f6Smrg    req->context_id = context->context_id;
3036f03b1f6Smrg    UnlockDisplay (dpy);
3046f03b1f6Smrg    SyncHandle ();
3056f03b1f6Smrg    return Success;
3066f03b1f6Smrg}
3076f03b1f6Smrg
3086f03b1f6Smrg
3096f03b1f6Smrg/*
3106f03b1f6Smrg   _xvmc_create_surface -
3116f03b1f6Smrg
3126f03b1f6Smrg   Pass the context and this function will fill out all the
31342941e3bSmrg   information in the surface.
3146f03b1f6Smrg   The server may return implementation-specific information
3156f03b1f6Smrg   back in the priv_data.  The size of that information will
3166f03b1f6Smrg   an array of priv_count CARD32s.  This data is allocated by
3176f03b1f6Smrg   this function.  If returned, the caller is responsible for
3186f03b1f6Smrg   freeing it!  Generally, such information is returned only if
3196f03b1f6Smrg   the context was a direct context.
32042941e3bSmrg
3216f03b1f6Smrg*/
3226f03b1f6Smrg
3236f03b1f6SmrgStatus _xvmc_create_surface (
3246f03b1f6Smrg    Display *dpy,
3256f03b1f6Smrg    XvMCContext *context,
3266f03b1f6Smrg    XvMCSurface *surface,
3276f03b1f6Smrg    int *priv_count,
3286f03b1f6Smrg    CARD32 **priv_data
3296f03b1f6Smrg)
3306f03b1f6Smrg{
3316f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
3326f03b1f6Smrg    xvmcCreateSurfaceReply rep;
3336f03b1f6Smrg    xvmcCreateSurfaceReq  *req;
3346f03b1f6Smrg
3356f03b1f6Smrg    *priv_count = 0;
3366f03b1f6Smrg    *priv_data = NULL;
3376f03b1f6Smrg
3386f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
3396f03b1f6Smrg
3406f03b1f6Smrg    LockDisplay (dpy);
3416f03b1f6Smrg    XvMCGetReq (CreateSurface, req);
3426f03b1f6Smrg
3436f03b1f6Smrg    surface->surface_id = XAllocID(dpy);
3446f03b1f6Smrg    surface->context_id = context->context_id;
3456f03b1f6Smrg    surface->surface_type_id = context->surface_type_id;
3466f03b1f6Smrg    surface->width = context->width;
3476f03b1f6Smrg    surface->height = context->height;
3486f03b1f6Smrg
3496f03b1f6Smrg    req->surface_id = surface->surface_id;
3506f03b1f6Smrg    req->context_id = surface->context_id;
3516f03b1f6Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
3526f03b1f6Smrg        UnlockDisplay (dpy);
3536f03b1f6Smrg        SyncHandle ();
3546f03b1f6Smrg        return BadImplementation;
3556f03b1f6Smrg    }
3566f03b1f6Smrg
3576f03b1f6Smrg    if(rep.length) {
3586f03b1f6Smrg        *priv_data = Xmalloc(rep.length << 2);
3596f03b1f6Smrg        if(*priv_data) {
3606f03b1f6Smrg            _XRead(dpy, (char*)(*priv_data), rep.length << 2);
3616f03b1f6Smrg            *priv_count = rep.length;
3626f03b1f6Smrg        } else
3636f03b1f6Smrg            _XEatData(dpy, rep.length << 2);
3646f03b1f6Smrg    }
3656f03b1f6Smrg
3666f03b1f6Smrg    UnlockDisplay (dpy);
3676f03b1f6Smrg    SyncHandle ();
3686f03b1f6Smrg    return Success;
3696f03b1f6Smrg}
3706f03b1f6Smrg
3716f03b1f6SmrgStatus _xvmc_destroy_surface (
3726f03b1f6Smrg    Display *dpy,
3736f03b1f6Smrg    XvMCSurface *surface
3746f03b1f6Smrg)
3756f03b1f6Smrg{
3766f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
3776f03b1f6Smrg    xvmcDestroySurfaceReq  *req;
3786f03b1f6Smrg
3796f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
3806f03b1f6Smrg
3816f03b1f6Smrg    LockDisplay (dpy);
3826f03b1f6Smrg    XvMCGetReq (DestroySurface, req);
3836f03b1f6Smrg    req->surface_id = surface->surface_id;
3846f03b1f6Smrg    UnlockDisplay (dpy);
3856f03b1f6Smrg    SyncHandle ();
3866f03b1f6Smrg    return Success;
3876f03b1f6Smrg}
3886f03b1f6Smrg
3896f03b1f6Smrg/*
3906f03b1f6Smrg   _xvmc_create_subpicture -
3916f03b1f6Smrg
3926f03b1f6Smrg   Pass the subpicture with the width, height and xvimage_id filled
3936f03b1f6Smrg   out and this function will fill out everything else in the
3946f03b1f6Smrg   subpicture as well as adjust the width and height if needed.
3956f03b1f6Smrg   The server may return implementation-specific information
3966f03b1f6Smrg   back in the priv_data.  The size of that information will
3976f03b1f6Smrg   an array of priv_count CARD32s.  This data is allocated by
3986f03b1f6Smrg   this function.  If returned, the caller is responsible for
3996f03b1f6Smrg   freeing it!  Generally, such information is returned only if
4006f03b1f6Smrg   the context was a direct context.
4016f03b1f6Smrg
4026f03b1f6Smrg*/
4036f03b1f6Smrg
4046f03b1f6SmrgStatus _xvmc_create_subpicture (
4056f03b1f6Smrg    Display *dpy,
4066f03b1f6Smrg    XvMCContext *context,
4076f03b1f6Smrg    XvMCSubpicture *subpicture,
4086f03b1f6Smrg    int *priv_count,
4096f03b1f6Smrg    CARD32 **priv_data
4106f03b1f6Smrg)
4116f03b1f6Smrg{
4126f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
4136f03b1f6Smrg    xvmcCreateSubpictureReply rep;
4146f03b1f6Smrg    xvmcCreateSubpictureReq  *req;
4156f03b1f6Smrg
4166f03b1f6Smrg    *priv_count = 0;
4176f03b1f6Smrg    *priv_data = NULL;
4186f03b1f6Smrg
4196f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
4206f03b1f6Smrg
4216f03b1f6Smrg    LockDisplay (dpy);
4226f03b1f6Smrg    XvMCGetReq (CreateSubpicture, req);
4236f03b1f6Smrg
4246f03b1f6Smrg    subpicture->subpicture_id = XAllocID(dpy);
4256f03b1f6Smrg    subpicture->context_id = context->context_id;
4266f03b1f6Smrg
4276f03b1f6Smrg    req->subpicture_id = subpicture->subpicture_id;
4286f03b1f6Smrg    req->context_id = subpicture->context_id;
4296f03b1f6Smrg    req->xvimage_id = subpicture->xvimage_id;
4306f03b1f6Smrg    req->width = subpicture->width;
4316f03b1f6Smrg    req->height = subpicture->height;
4326f03b1f6Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
4336f03b1f6Smrg        UnlockDisplay (dpy);
4346f03b1f6Smrg        SyncHandle ();
4356f03b1f6Smrg        return BadImplementation;
4366f03b1f6Smrg    }
4376f03b1f6Smrg
4386f03b1f6Smrg    subpicture->width = rep.width_actual;
4396f03b1f6Smrg    subpicture->height = rep.height_actual;
4406f03b1f6Smrg    subpicture->num_palette_entries = rep.num_palette_entries;
4416f03b1f6Smrg    subpicture->entry_bytes = rep.entry_bytes;
4426f03b1f6Smrg    subpicture->component_order[0] = rep.component_order[0];
4436f03b1f6Smrg    subpicture->component_order[1] = rep.component_order[1];
4446f03b1f6Smrg    subpicture->component_order[2] = rep.component_order[2];
4456f03b1f6Smrg    subpicture->component_order[3] = rep.component_order[3];
4466f03b1f6Smrg
4476f03b1f6Smrg    if(rep.length) {
4486f03b1f6Smrg        *priv_data = Xmalloc(rep.length << 2);
4496f03b1f6Smrg        if(*priv_data) {
4506f03b1f6Smrg            _XRead(dpy, (char*)(*priv_data), rep.length << 2);
4516f03b1f6Smrg            *priv_count = rep.length;
4526f03b1f6Smrg        } else
4536f03b1f6Smrg            _XEatData(dpy, rep.length << 2);
4546f03b1f6Smrg    }
4556f03b1f6Smrg
4566f03b1f6Smrg    UnlockDisplay (dpy);
4576f03b1f6Smrg    SyncHandle ();
4586f03b1f6Smrg    return Success;
4596f03b1f6Smrg}
4606f03b1f6Smrg
4616f03b1f6SmrgStatus _xvmc_destroy_subpicture(
4626f03b1f6Smrg    Display *dpy,
4636f03b1f6Smrg    XvMCSubpicture *subpicture
4646f03b1f6Smrg)
4656f03b1f6Smrg{
4666f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
4676f03b1f6Smrg    xvmcDestroySubpictureReq  *req;
4686f03b1f6Smrg
4696f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
4706f03b1f6Smrg
4716f03b1f6Smrg    LockDisplay (dpy);
4726f03b1f6Smrg    XvMCGetReq (DestroySubpicture, req);
47342941e3bSmrg    req->subpicture_id = subpicture->subpicture_id;
4746f03b1f6Smrg    UnlockDisplay (dpy);
4756f03b1f6Smrg    SyncHandle ();
4766f03b1f6Smrg    return Success;
4776f03b1f6Smrg}
4786f03b1f6Smrg
4796f03b1f6SmrgStatus XvMCGetDRInfo(Display *dpy, XvPortID port,
48042941e3bSmrg		     char **name, char **busID,
48142941e3bSmrg		     int *major, int *minor,
4826f03b1f6Smrg		     int *patchLevel,
4836f03b1f6Smrg		     int *isLocal)
4846f03b1f6Smrg{
4856f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
4866f03b1f6Smrg    xvmcGetDRInfoReply rep;
4876f03b1f6Smrg    xvmcGetDRInfoReq  *req;
4886f03b1f6Smrg    CARD32 magic;
4896f03b1f6Smrg
49042941e3bSmrg#ifdef HAVE_SHMAT
4916f03b1f6Smrg    volatile CARD32 *shMem;
4926f03b1f6Smrg    struct timezone here;
4936f03b1f6Smrg    struct timeval now;
4946f03b1f6Smrg    here.tz_minuteswest = 0;
4956f03b1f6Smrg    here.tz_dsttime = 0;
4966f03b1f6Smrg#endif
4976f03b1f6Smrg
498190694daSmrg    *name = NULL;
499190694daSmrg    *busID = NULL;
500190694daSmrg
5016f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
5026f03b1f6Smrg
5036f03b1f6Smrg    LockDisplay (dpy);
5046f03b1f6Smrg    XvMCGetReq (GetDRInfo, req);
5056f03b1f6Smrg
5066f03b1f6Smrg    req->port = port;
5076f03b1f6Smrg    magic = 0;
5086f03b1f6Smrg    req->magic = 0;
50942941e3bSmrg#ifdef HAVE_SHMAT
5106f03b1f6Smrg    req->shmKey = shmget(IPC_PRIVATE, 1024, IPC_CREAT | 0600);
5116f03b1f6Smrg
5126f03b1f6Smrg    /*
5136f03b1f6Smrg     * We fill a shared memory page with a repetitive pattern. If the
5146f03b1f6Smrg     * X server can read this pattern, we probably have a local connection.
5156f03b1f6Smrg     * Note that we can trigger the remote X server to read any shared
5166f03b1f6Smrg     * page on the remote machine, so we shouldn't be able to guess and verify
5176f03b1f6Smrg     * any complicated data on those pages. Thats the explanation of this
5186f03b1f6Smrg     * otherwise stupid-looking pattern algorithm.
5196f03b1f6Smrg     */
52042941e3bSmrg
5216f03b1f6Smrg    if (req->shmKey >= 0) {
5226f03b1f6Smrg	shMem = (CARD32 *) shmat(req->shmKey, NULL, 0);
5236f03b1f6Smrg	shmctl( req->shmKey, IPC_RMID, NULL);
52442941e3bSmrg	if ( shMem ) {
5256f03b1f6Smrg
5266f03b1f6Smrg	    register volatile CARD32 *shMemC = shMem;
5276f03b1f6Smrg	    register int i;
5286f03b1f6Smrg
5296f03b1f6Smrg	    gettimeofday( &now, &here);
5306f03b1f6Smrg	    magic = now.tv_usec & 0x000FFFFF;
5316f03b1f6Smrg	    req->magic = magic;
5326f03b1f6Smrg	    i = 1024 / sizeof(CARD32);
5336f03b1f6Smrg	    while(i--) {
53442941e3bSmrg	        *shMemC++ = magic;
5356f03b1f6Smrg	        magic = ~magic;
5366f03b1f6Smrg	    }
5376f03b1f6Smrg	} else {
5386f03b1f6Smrg	    req->shmKey = -1;
5396f03b1f6Smrg	}
5406f03b1f6Smrg    }
5416f03b1f6Smrg#else
5426f03b1f6Smrg    req->shmKey = 0;
5436f03b1f6Smrg#endif
5446f03b1f6Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
5456f03b1f6Smrg        UnlockDisplay (dpy);
5466f03b1f6Smrg        SyncHandle ();
54742941e3bSmrg#ifdef HAVE_SHMAT
5486f03b1f6Smrg	if ( req->shmKey >= 0) {
5496f03b1f6Smrg	    shmdt( (const void *) shMem );
55042941e3bSmrg	}
5516f03b1f6Smrg#endif
5526f03b1f6Smrg        return -1;
5536f03b1f6Smrg    }
55442941e3bSmrg#ifdef HAVE_SHMAT
5556f03b1f6Smrg    shmdt( (const void *) shMem );
5566f03b1f6Smrg#endif
5576f03b1f6Smrg
5586f03b1f6Smrg    if (rep.length > 0) {
559190694daSmrg	unsigned long realSize = 0;
560190694daSmrg	char *tmpBuf = NULL;
561190694daSmrg
562190694daSmrg	if (rep.length < (INT_MAX >> 2)) {
563190694daSmrg	    realSize = rep.length << 2;
564190694daSmrg	    if (realSize >= (rep.nameLen + rep.busIDLen)) {
565190694daSmrg		tmpBuf = Xmalloc(realSize);
566190694daSmrg		*name = Xmalloc(rep.nameLen);
567190694daSmrg		*busID = Xmalloc(rep.busIDLen);
56842941e3bSmrg	    }
5696f03b1f6Smrg	}
5706f03b1f6Smrg
5716f03b1f6Smrg	if (*name && *busID && tmpBuf) {
5726f03b1f6Smrg	    _XRead(dpy, tmpBuf, realSize);
5736f03b1f6Smrg	    strncpy(*name,tmpBuf,rep.nameLen);
574190694daSmrg	    name[rep.nameLen - 1] = '\0';
5756f03b1f6Smrg	    strncpy(*busID,tmpBuf+rep.nameLen,rep.busIDLen);
576190694daSmrg	    busID[rep.busIDLen - 1] = '\0';
5776f03b1f6Smrg	    XFree(tmpBuf);
5786f03b1f6Smrg	} else {
579190694daSmrg	    XFree(*name);
580190694daSmrg	    *name = NULL;
581190694daSmrg	    XFree(*busID);
582190694daSmrg	    *name = NULL;
583190694daSmrg	    XFree(tmpBuf);
5846f03b1f6Smrg
5856f03b1f6Smrg	    _XEatData(dpy, realSize);
5866f03b1f6Smrg	    UnlockDisplay (dpy);
5876f03b1f6Smrg	    SyncHandle ();
5886f03b1f6Smrg	    return -1;
5896f03b1f6Smrg
5906f03b1f6Smrg	}
5916f03b1f6Smrg    }
5926f03b1f6Smrg
5936f03b1f6Smrg    UnlockDisplay (dpy);
5946f03b1f6Smrg    SyncHandle ();
5956f03b1f6Smrg    *major = rep.major;
5966f03b1f6Smrg    *minor = rep.minor;
5976f03b1f6Smrg    *patchLevel = rep.patchLevel;
5986f03b1f6Smrg    *isLocal = (req->shmKey > 0) ? rep.isLocal : 1;
5996f03b1f6Smrg    return (rep.length > 0) ? Success : BadImplementation;
6006f03b1f6Smrg}
6016f03b1f6Smrg
602