XvMC.c revision 42941e3b
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>
196f03b1f6Smrg
206f03b1f6Smrgstatic XExtensionInfo _xvmc_info_data;
216f03b1f6Smrgstatic XExtensionInfo *xvmc_info = &_xvmc_info_data;
2242941e3bSmrgstatic const char *xvmc_extension_name = XvMCName;
236f03b1f6Smrg
2442941e3bSmrgstatic const char *xvmc_error_list[] =
256f03b1f6Smrg{
266f03b1f6Smrg   "BadContext",
276f03b1f6Smrg   "BadSurface",
286f03b1f6Smrg   "BadSubpicture"
296f03b1f6Smrg};
306f03b1f6Smrg
316f03b1f6Smrgstatic XEXT_GENERATE_CLOSE_DISPLAY (xvmc_close_display, xvmc_info)
326f03b1f6Smrg
336f03b1f6Smrg
346f03b1f6Smrgstatic XEXT_GENERATE_ERROR_STRING (xvmc_error_string, xvmc_extension_name,
356f03b1f6Smrg                                   XvMCNumErrors, xvmc_error_list)
366f03b1f6Smrg
376f03b1f6Smrg
386f03b1f6Smrgstatic XExtensionHooks xvmc_extension_hooks = {
396f03b1f6Smrg    NULL,                               /* create_gc */
406f03b1f6Smrg    NULL,                               /* copy_gc */
416f03b1f6Smrg    NULL,                               /* flush_gc */
426f03b1f6Smrg    NULL,                               /* free_gc */
436f03b1f6Smrg    NULL,                               /* create_font */
446f03b1f6Smrg    NULL,                               /* free_font */
456f03b1f6Smrg    xvmc_close_display,                 /* close_display */
466f03b1f6Smrg    NULL,                               /* wire_to_event */
476f03b1f6Smrg    NULL,                               /* event_to_wire */
486f03b1f6Smrg    NULL,                               /* error */
496f03b1f6Smrg    xvmc_error_string                   /* error_string */
506f03b1f6Smrg};
516f03b1f6Smrg
526f03b1f6Smrgstatic XEXT_GENERATE_FIND_DISPLAY (xvmc_find_display, xvmc_info,
536f03b1f6Smrg                                   xvmc_extension_name,
546f03b1f6Smrg                                   &xvmc_extension_hooks,
556f03b1f6Smrg                                   XvMCNumEvents, NULL)
566f03b1f6Smrg
576f03b1f6SmrgBool XvMCQueryExtension (Display *dpy, int *event_basep, int *error_basep)
586f03b1f6Smrg{
596f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
606f03b1f6Smrg
616f03b1f6Smrg    if (XextHasExtension(info)) {
626f03b1f6Smrg        *event_basep = info->codes->first_event;
636f03b1f6Smrg        *error_basep = info->codes->first_error;
646f03b1f6Smrg        return True;
656f03b1f6Smrg    } else {
666f03b1f6Smrg        return False;
676f03b1f6Smrg    }
686f03b1f6Smrg}
696f03b1f6Smrg
706f03b1f6SmrgStatus XvMCQueryVersion (Display *dpy, int *major, int *minor)
716f03b1f6Smrg{
726f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
736f03b1f6Smrg    xvmcQueryVersionReply rep;
746f03b1f6Smrg    xvmcQueryVersionReq  *req;
756f03b1f6Smrg
766f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
776f03b1f6Smrg
786f03b1f6Smrg    LockDisplay (dpy);
796f03b1f6Smrg    XvMCGetReq (QueryVersion, req);
806f03b1f6Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
816f03b1f6Smrg        UnlockDisplay (dpy);
826f03b1f6Smrg        SyncHandle ();
836f03b1f6Smrg        return BadImplementation;
846f03b1f6Smrg    }
856f03b1f6Smrg    *major = rep.major;
866f03b1f6Smrg    *minor = rep.minor;
876f03b1f6Smrg    UnlockDisplay (dpy);
886f03b1f6Smrg    SyncHandle ();
896f03b1f6Smrg    return Success;
906f03b1f6Smrg}
916f03b1f6Smrg
926f03b1f6Smrg
936f03b1f6SmrgXvMCSurfaceInfo * XvMCListSurfaceTypes(Display *dpy, XvPortID port, int *num)
946f03b1f6Smrg{
956f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
966f03b1f6Smrg    xvmcListSurfaceTypesReply rep;
976f03b1f6Smrg    xvmcListSurfaceTypesReq  *req;
986f03b1f6Smrg    XvMCSurfaceInfo *surface_info = NULL;
996f03b1f6Smrg
1006f03b1f6Smrg    *num = 0;
1016f03b1f6Smrg
1026f03b1f6Smrg    XvMCCheckExtension (dpy, info, NULL);
10342941e3bSmrg
1046f03b1f6Smrg    LockDisplay (dpy);
1056f03b1f6Smrg    XvMCGetReq (ListSurfaceTypes, req);
1066f03b1f6Smrg    req->port = port;
1076f03b1f6Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
1086f03b1f6Smrg        UnlockDisplay (dpy);
1096f03b1f6Smrg        SyncHandle ();
1106f03b1f6Smrg        return NULL;
1116f03b1f6Smrg    }
1126f03b1f6Smrg
1136f03b1f6Smrg    if(rep.num > 0) {
11442941e3bSmrg	surface_info =
1156f03b1f6Smrg	    (XvMCSurfaceInfo*)Xmalloc(rep.num * sizeof(XvMCSurfaceInfo));
1166f03b1f6Smrg
1176f03b1f6Smrg        if(surface_info) {
1186f03b1f6Smrg	    xvmcSurfaceInfo sinfo;
1196f03b1f6Smrg	    int i;
1206f03b1f6Smrg
1216f03b1f6Smrg	    *num = rep.num;
1226f03b1f6Smrg
1236f03b1f6Smrg	    for(i = 0; i < rep.num; i++) {
1246f03b1f6Smrg		_XRead(dpy, (char*)&sinfo, sizeof(xvmcSurfaceInfo));
1256f03b1f6Smrg	       surface_info[i].surface_type_id = sinfo.surface_type_id;
1266f03b1f6Smrg	       surface_info[i].chroma_format = sinfo.chroma_format;
1276f03b1f6Smrg	       surface_info[i].max_width = sinfo.max_width;
1286f03b1f6Smrg	       surface_info[i].max_height = sinfo.max_height;
12942941e3bSmrg	       surface_info[i].subpicture_max_width =
1306f03b1f6Smrg					sinfo.subpicture_max_width;
13142941e3bSmrg	       surface_info[i].subpicture_max_height =
1326f03b1f6Smrg					sinfo.subpicture_max_height;
1336f03b1f6Smrg	       surface_info[i].mc_type = sinfo.mc_type;
1346f03b1f6Smrg	       surface_info[i].flags = sinfo.flags;
1356f03b1f6Smrg	    }
1366f03b1f6Smrg	} else
1376f03b1f6Smrg	   _XEatData(dpy, rep.length << 2);
1386f03b1f6Smrg    }
1396f03b1f6Smrg
1406f03b1f6Smrg    UnlockDisplay (dpy);
1416f03b1f6Smrg    SyncHandle ();
1426f03b1f6Smrg    return surface_info;
1436f03b1f6Smrg}
1446f03b1f6Smrg
1456f03b1f6Smrg
1466f03b1f6SmrgXvImageFormatValues * XvMCListSubpictureTypes (
1476f03b1f6Smrg  Display * dpy,
1486f03b1f6Smrg  XvPortID port,
1496f03b1f6Smrg  int surface_type_id,
1506f03b1f6Smrg  int *count_return
1516f03b1f6Smrg)
1526f03b1f6Smrg{
1536f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
1546f03b1f6Smrg    xvmcListSubpictureTypesReply rep;
1556f03b1f6Smrg    xvmcListSubpictureTypesReq  *req;
1566f03b1f6Smrg    XvImageFormatValues *ret = NULL;
1576f03b1f6Smrg
1586f03b1f6Smrg
1596f03b1f6Smrg    *count_return = 0;
1606f03b1f6Smrg
1616f03b1f6Smrg    XvMCCheckExtension (dpy, info, NULL);
1626f03b1f6Smrg
1636f03b1f6Smrg
1646f03b1f6Smrg    LockDisplay (dpy);
1656f03b1f6Smrg    XvMCGetReq (ListSubpictureTypes, req);
1666f03b1f6Smrg    req->port = port;
1676f03b1f6Smrg    req->surface_type_id = surface_type_id;
1686f03b1f6Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
1696f03b1f6Smrg        UnlockDisplay (dpy);
1706f03b1f6Smrg        SyncHandle ();
1716f03b1f6Smrg        return NULL;
1726f03b1f6Smrg    }
1736f03b1f6Smrg
1746f03b1f6Smrg    if(rep.num > 0) {
17542941e3bSmrg        ret =
1766f03b1f6Smrg	   (XvImageFormatValues*)Xmalloc(rep.num * sizeof(XvImageFormatValues));
1776f03b1f6Smrg
1786f03b1f6Smrg        if(ret) {
1796f03b1f6Smrg            xvImageFormatInfo Info;
1806f03b1f6Smrg            int i;
1816f03b1f6Smrg
1826f03b1f6Smrg            *count_return = rep.num;
1836f03b1f6Smrg
1846f03b1f6Smrg            for(i = 0; i < rep.num; i++) {
1856f03b1f6Smrg              _XRead(dpy, (char*)(&Info), sz_xvImageFormatInfo);
18642941e3bSmrg              ret[i].id = Info.id;
18742941e3bSmrg              ret[i].type = Info.type;
18842941e3bSmrg              ret[i].byte_order = Info.byte_order;
1896f03b1f6Smrg              memcpy(&(ret[i].guid[0]), &(Info.guid[0]), 16);
19042941e3bSmrg              ret[i].bits_per_pixel = Info.bpp;
19142941e3bSmrg              ret[i].format = Info.format;
19242941e3bSmrg              ret[i].num_planes = Info.num_planes;
19342941e3bSmrg              ret[i].depth = Info.depth;
19442941e3bSmrg              ret[i].red_mask = Info.red_mask;
19542941e3bSmrg              ret[i].green_mask = Info.green_mask;
19642941e3bSmrg              ret[i].blue_mask = Info.blue_mask;
19742941e3bSmrg              ret[i].y_sample_bits = Info.y_sample_bits;
19842941e3bSmrg              ret[i].u_sample_bits = Info.u_sample_bits;
1996f03b1f6Smrg              ret[i].v_sample_bits = Info.v_sample_bits;
2006f03b1f6Smrg              ret[i].horz_y_period = Info.horz_y_period;
2016f03b1f6Smrg              ret[i].horz_u_period = Info.horz_u_period;
2026f03b1f6Smrg              ret[i].horz_v_period = Info.horz_v_period;
2036f03b1f6Smrg              ret[i].vert_y_period = Info.vert_y_period;
2046f03b1f6Smrg              ret[i].vert_u_period = Info.vert_u_period;
2056f03b1f6Smrg              ret[i].vert_v_period = Info.vert_v_period;
2066f03b1f6Smrg              memcpy(&(ret[i].component_order[0]), &(Info.comp_order[0]), 32);
2076f03b1f6Smrg              ret[i].scanline_order = Info.scanline_order;
2086f03b1f6Smrg            }
2096f03b1f6Smrg        } else
2106f03b1f6Smrg	   _XEatData(dpy, rep.length << 2);
2116f03b1f6Smrg    }
2126f03b1f6Smrg
2136f03b1f6Smrg    UnlockDisplay (dpy);
2146f03b1f6Smrg    SyncHandle ();
21542941e3bSmrg    return ret;
2166f03b1f6Smrg}
2176f03b1f6Smrg
2186f03b1f6Smrg
21942941e3bSmrg/******************************************************************
2206f03b1f6Smrg   These are intended as a protocol interface to be used by direct
2216f03b1f6Smrg   rendering libraries.  They are not intended to be client viewable
2226f03b1f6Smrg   functions.  These will stay in place until we have a mechanism in
2236f03b1f6Smrg   place similar to that of OpenGL with an libXvMCcore library.
22442941e3bSmrg*******************************************************************/
22542941e3bSmrg
22642941e3bSmrg/*
2276f03b1f6Smrg   _xvmc_create_context -
2286f03b1f6Smrg
2296f03b1f6Smrg   Pass in the context with the surface_type_id, width, height,
2306f03b1f6Smrg   port and flags filled out.  This function will fill out the
2316f03b1f6Smrg   context_id and update the width, height and flags field.
2326f03b1f6Smrg   The server may return implementation-specific information
2336f03b1f6Smrg   back in the priv_data.  The size of that information will
2346f03b1f6Smrg   an array of priv_count CARD32s.  This data is allocated by
2356f03b1f6Smrg   this function.  If returned, the caller is responsible for
2366f03b1f6Smrg   freeing it!  Generally, such information is only returned if
23742941e3bSmrg   an XVMC_DIRECT context was specified.
2386f03b1f6Smrg*/
2396f03b1f6Smrg
2406f03b1f6Smrg
2416f03b1f6SmrgStatus _xvmc_create_context (
2426f03b1f6Smrg    Display *dpy,
2436f03b1f6Smrg    XvMCContext *context,
2446f03b1f6Smrg    int *priv_count,
2456f03b1f6Smrg    CARD32 **priv_data
2466f03b1f6Smrg)
2476f03b1f6Smrg{
2486f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
2496f03b1f6Smrg    xvmcCreateContextReply rep;
2506f03b1f6Smrg    xvmcCreateContextReq  *req;
2516f03b1f6Smrg
2526f03b1f6Smrg    *priv_count = 0;
2536f03b1f6Smrg    *priv_data = NULL;
2546f03b1f6Smrg
2556f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
2566f03b1f6Smrg
2576f03b1f6Smrg    LockDisplay (dpy);
2586f03b1f6Smrg    XvMCGetReq (CreateContext, req);
2596f03b1f6Smrg    context->context_id = XAllocID(dpy);
2606f03b1f6Smrg    req->context_id = context->context_id;
2616f03b1f6Smrg    req->port = context->port;
2626f03b1f6Smrg    req->surface_type_id = context->surface_type_id;
2636f03b1f6Smrg    req->width = context->width;
2646f03b1f6Smrg    req->height = context->height;
2656f03b1f6Smrg    req->flags = context->flags;
2666f03b1f6Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
2676f03b1f6Smrg        UnlockDisplay (dpy);
2686f03b1f6Smrg        SyncHandle ();
2696f03b1f6Smrg        return BadImplementation;
2706f03b1f6Smrg    }
2716f03b1f6Smrg    context->width = rep.width_actual;
2726f03b1f6Smrg    context->height = rep.height_actual;
2736f03b1f6Smrg    context->flags = rep.flags_return;
2746f03b1f6Smrg
2756f03b1f6Smrg    if(rep.length) {
2766f03b1f6Smrg	*priv_data = Xmalloc(rep.length << 2);
2776f03b1f6Smrg	if(*priv_data) {
2786f03b1f6Smrg            _XRead(dpy, (char*)(*priv_data), rep.length << 2);
2796f03b1f6Smrg	    *priv_count = rep.length;
2806f03b1f6Smrg	} else
2816f03b1f6Smrg	    _XEatData(dpy, rep.length << 2);
2826f03b1f6Smrg    }
2836f03b1f6Smrg
2846f03b1f6Smrg    UnlockDisplay (dpy);
2856f03b1f6Smrg    SyncHandle ();
2866f03b1f6Smrg    return Success;
2876f03b1f6Smrg}
2886f03b1f6Smrg
2896f03b1f6SmrgStatus _xvmc_destroy_context (
2906f03b1f6Smrg    Display *dpy,
2916f03b1f6Smrg    XvMCContext *context
2926f03b1f6Smrg)
2936f03b1f6Smrg{
2946f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
2956f03b1f6Smrg    xvmcDestroyContextReq  *req;
2966f03b1f6Smrg
2976f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
2986f03b1f6Smrg
2996f03b1f6Smrg    LockDisplay (dpy);
3006f03b1f6Smrg    XvMCGetReq (DestroyContext, req);
3016f03b1f6Smrg    req->context_id = context->context_id;
3026f03b1f6Smrg    UnlockDisplay (dpy);
3036f03b1f6Smrg    SyncHandle ();
3046f03b1f6Smrg    return Success;
3056f03b1f6Smrg}
3066f03b1f6Smrg
3076f03b1f6Smrg
3086f03b1f6Smrg/*
3096f03b1f6Smrg   _xvmc_create_surface -
3106f03b1f6Smrg
3116f03b1f6Smrg   Pass the context and this function will fill out all the
31242941e3bSmrg   information in the surface.
3136f03b1f6Smrg   The server may return implementation-specific information
3146f03b1f6Smrg   back in the priv_data.  The size of that information will
3156f03b1f6Smrg   an array of priv_count CARD32s.  This data is allocated by
3166f03b1f6Smrg   this function.  If returned, the caller is responsible for
3176f03b1f6Smrg   freeing it!  Generally, such information is returned only if
3186f03b1f6Smrg   the context was a direct context.
31942941e3bSmrg
3206f03b1f6Smrg*/
3216f03b1f6Smrg
3226f03b1f6SmrgStatus _xvmc_create_surface (
3236f03b1f6Smrg    Display *dpy,
3246f03b1f6Smrg    XvMCContext *context,
3256f03b1f6Smrg    XvMCSurface *surface,
3266f03b1f6Smrg    int *priv_count,
3276f03b1f6Smrg    CARD32 **priv_data
3286f03b1f6Smrg)
3296f03b1f6Smrg{
3306f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
3316f03b1f6Smrg    xvmcCreateSurfaceReply rep;
3326f03b1f6Smrg    xvmcCreateSurfaceReq  *req;
3336f03b1f6Smrg
3346f03b1f6Smrg    *priv_count = 0;
3356f03b1f6Smrg    *priv_data = NULL;
3366f03b1f6Smrg
3376f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
3386f03b1f6Smrg
3396f03b1f6Smrg    LockDisplay (dpy);
3406f03b1f6Smrg    XvMCGetReq (CreateSurface, req);
3416f03b1f6Smrg
3426f03b1f6Smrg    surface->surface_id = XAllocID(dpy);
3436f03b1f6Smrg    surface->context_id = context->context_id;
3446f03b1f6Smrg    surface->surface_type_id = context->surface_type_id;
3456f03b1f6Smrg    surface->width = context->width;
3466f03b1f6Smrg    surface->height = context->height;
3476f03b1f6Smrg
3486f03b1f6Smrg    req->surface_id = surface->surface_id;
3496f03b1f6Smrg    req->context_id = surface->context_id;
3506f03b1f6Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
3516f03b1f6Smrg        UnlockDisplay (dpy);
3526f03b1f6Smrg        SyncHandle ();
3536f03b1f6Smrg        return BadImplementation;
3546f03b1f6Smrg    }
3556f03b1f6Smrg
3566f03b1f6Smrg    if(rep.length) {
3576f03b1f6Smrg        *priv_data = Xmalloc(rep.length << 2);
3586f03b1f6Smrg        if(*priv_data) {
3596f03b1f6Smrg            _XRead(dpy, (char*)(*priv_data), rep.length << 2);
3606f03b1f6Smrg            *priv_count = rep.length;
3616f03b1f6Smrg        } else
3626f03b1f6Smrg            _XEatData(dpy, rep.length << 2);
3636f03b1f6Smrg    }
3646f03b1f6Smrg
3656f03b1f6Smrg    UnlockDisplay (dpy);
3666f03b1f6Smrg    SyncHandle ();
3676f03b1f6Smrg    return Success;
3686f03b1f6Smrg}
3696f03b1f6Smrg
3706f03b1f6SmrgStatus _xvmc_destroy_surface (
3716f03b1f6Smrg    Display *dpy,
3726f03b1f6Smrg    XvMCSurface *surface
3736f03b1f6Smrg)
3746f03b1f6Smrg{
3756f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
3766f03b1f6Smrg    xvmcDestroySurfaceReq  *req;
3776f03b1f6Smrg
3786f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
3796f03b1f6Smrg
3806f03b1f6Smrg    LockDisplay (dpy);
3816f03b1f6Smrg    XvMCGetReq (DestroySurface, req);
3826f03b1f6Smrg    req->surface_id = surface->surface_id;
3836f03b1f6Smrg    UnlockDisplay (dpy);
3846f03b1f6Smrg    SyncHandle ();
3856f03b1f6Smrg    return Success;
3866f03b1f6Smrg}
3876f03b1f6Smrg
3886f03b1f6Smrg/*
3896f03b1f6Smrg   _xvmc_create_subpicture -
3906f03b1f6Smrg
3916f03b1f6Smrg   Pass the subpicture with the width, height and xvimage_id filled
3926f03b1f6Smrg   out and this function will fill out everything else in the
3936f03b1f6Smrg   subpicture as well as adjust the width and height if needed.
3946f03b1f6Smrg   The server may return implementation-specific information
3956f03b1f6Smrg   back in the priv_data.  The size of that information will
3966f03b1f6Smrg   an array of priv_count CARD32s.  This data is allocated by
3976f03b1f6Smrg   this function.  If returned, the caller is responsible for
3986f03b1f6Smrg   freeing it!  Generally, such information is returned only if
3996f03b1f6Smrg   the context was a direct context.
4006f03b1f6Smrg
4016f03b1f6Smrg*/
4026f03b1f6Smrg
4036f03b1f6SmrgStatus _xvmc_create_subpicture (
4046f03b1f6Smrg    Display *dpy,
4056f03b1f6Smrg    XvMCContext *context,
4066f03b1f6Smrg    XvMCSubpicture *subpicture,
4076f03b1f6Smrg    int *priv_count,
4086f03b1f6Smrg    CARD32 **priv_data
4096f03b1f6Smrg)
4106f03b1f6Smrg{
4116f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
4126f03b1f6Smrg    xvmcCreateSubpictureReply rep;
4136f03b1f6Smrg    xvmcCreateSubpictureReq  *req;
4146f03b1f6Smrg
4156f03b1f6Smrg    *priv_count = 0;
4166f03b1f6Smrg    *priv_data = NULL;
4176f03b1f6Smrg
4186f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
4196f03b1f6Smrg
4206f03b1f6Smrg    LockDisplay (dpy);
4216f03b1f6Smrg    XvMCGetReq (CreateSubpicture, req);
4226f03b1f6Smrg
4236f03b1f6Smrg    subpicture->subpicture_id = XAllocID(dpy);
4246f03b1f6Smrg    subpicture->context_id = context->context_id;
4256f03b1f6Smrg
4266f03b1f6Smrg    req->subpicture_id = subpicture->subpicture_id;
4276f03b1f6Smrg    req->context_id = subpicture->context_id;
4286f03b1f6Smrg    req->xvimage_id = subpicture->xvimage_id;
4296f03b1f6Smrg    req->width = subpicture->width;
4306f03b1f6Smrg    req->height = subpicture->height;
4316f03b1f6Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
4326f03b1f6Smrg        UnlockDisplay (dpy);
4336f03b1f6Smrg        SyncHandle ();
4346f03b1f6Smrg        return BadImplementation;
4356f03b1f6Smrg    }
4366f03b1f6Smrg
4376f03b1f6Smrg    subpicture->width = rep.width_actual;
4386f03b1f6Smrg    subpicture->height = rep.height_actual;
4396f03b1f6Smrg    subpicture->num_palette_entries = rep.num_palette_entries;
4406f03b1f6Smrg    subpicture->entry_bytes = rep.entry_bytes;
4416f03b1f6Smrg    subpicture->component_order[0] = rep.component_order[0];
4426f03b1f6Smrg    subpicture->component_order[1] = rep.component_order[1];
4436f03b1f6Smrg    subpicture->component_order[2] = rep.component_order[2];
4446f03b1f6Smrg    subpicture->component_order[3] = rep.component_order[3];
4456f03b1f6Smrg
4466f03b1f6Smrg    if(rep.length) {
4476f03b1f6Smrg        *priv_data = Xmalloc(rep.length << 2);
4486f03b1f6Smrg        if(*priv_data) {
4496f03b1f6Smrg            _XRead(dpy, (char*)(*priv_data), rep.length << 2);
4506f03b1f6Smrg            *priv_count = rep.length;
4516f03b1f6Smrg        } else
4526f03b1f6Smrg            _XEatData(dpy, rep.length << 2);
4536f03b1f6Smrg    }
4546f03b1f6Smrg
4556f03b1f6Smrg    UnlockDisplay (dpy);
4566f03b1f6Smrg    SyncHandle ();
4576f03b1f6Smrg    return Success;
4586f03b1f6Smrg}
4596f03b1f6Smrg
4606f03b1f6SmrgStatus _xvmc_destroy_subpicture(
4616f03b1f6Smrg    Display *dpy,
4626f03b1f6Smrg    XvMCSubpicture *subpicture
4636f03b1f6Smrg)
4646f03b1f6Smrg{
4656f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
4666f03b1f6Smrg    xvmcDestroySubpictureReq  *req;
4676f03b1f6Smrg
4686f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
4696f03b1f6Smrg
4706f03b1f6Smrg    LockDisplay (dpy);
4716f03b1f6Smrg    XvMCGetReq (DestroySubpicture, req);
47242941e3bSmrg    req->subpicture_id = subpicture->subpicture_id;
4736f03b1f6Smrg    UnlockDisplay (dpy);
4746f03b1f6Smrg    SyncHandle ();
4756f03b1f6Smrg    return Success;
4766f03b1f6Smrg}
4776f03b1f6Smrg
4786f03b1f6SmrgStatus XvMCGetDRInfo(Display *dpy, XvPortID port,
47942941e3bSmrg		     char **name, char **busID,
48042941e3bSmrg		     int *major, int *minor,
4816f03b1f6Smrg		     int *patchLevel,
4826f03b1f6Smrg		     int *isLocal)
4836f03b1f6Smrg{
4846f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
4856f03b1f6Smrg    xvmcGetDRInfoReply rep;
4866f03b1f6Smrg    xvmcGetDRInfoReq  *req;
4876f03b1f6Smrg    char *tmpBuf = NULL;
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
4986f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
4996f03b1f6Smrg
5006f03b1f6Smrg    LockDisplay (dpy);
5016f03b1f6Smrg    XvMCGetReq (GetDRInfo, req);
5026f03b1f6Smrg
5036f03b1f6Smrg    req->port = port;
5046f03b1f6Smrg    magic = 0;
5056f03b1f6Smrg    req->magic = 0;
50642941e3bSmrg#ifdef HAVE_SHMAT
5076f03b1f6Smrg    req->shmKey = shmget(IPC_PRIVATE, 1024, IPC_CREAT | 0600);
5086f03b1f6Smrg
5096f03b1f6Smrg    /*
5106f03b1f6Smrg     * We fill a shared memory page with a repetitive pattern. If the
5116f03b1f6Smrg     * X server can read this pattern, we probably have a local connection.
5126f03b1f6Smrg     * Note that we can trigger the remote X server to read any shared
5136f03b1f6Smrg     * page on the remote machine, so we shouldn't be able to guess and verify
5146f03b1f6Smrg     * any complicated data on those pages. Thats the explanation of this
5156f03b1f6Smrg     * otherwise stupid-looking pattern algorithm.
5166f03b1f6Smrg     */
51742941e3bSmrg
5186f03b1f6Smrg    if (req->shmKey >= 0) {
5196f03b1f6Smrg	shMem = (CARD32 *) shmat(req->shmKey, NULL, 0);
5206f03b1f6Smrg	shmctl( req->shmKey, IPC_RMID, NULL);
52142941e3bSmrg	if ( shMem ) {
5226f03b1f6Smrg
5236f03b1f6Smrg	    register volatile CARD32 *shMemC = shMem;
5246f03b1f6Smrg	    register int i;
5256f03b1f6Smrg
5266f03b1f6Smrg	    gettimeofday( &now, &here);
5276f03b1f6Smrg	    magic = now.tv_usec & 0x000FFFFF;
5286f03b1f6Smrg	    req->magic = magic;
5296f03b1f6Smrg	    i = 1024 / sizeof(CARD32);
5306f03b1f6Smrg	    while(i--) {
53142941e3bSmrg	        *shMemC++ = magic;
5326f03b1f6Smrg	        magic = ~magic;
5336f03b1f6Smrg	    }
5346f03b1f6Smrg	} else {
5356f03b1f6Smrg	    req->shmKey = -1;
5366f03b1f6Smrg	}
5376f03b1f6Smrg    }
5386f03b1f6Smrg#else
5396f03b1f6Smrg    req->shmKey = 0;
5406f03b1f6Smrg#endif
5416f03b1f6Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
5426f03b1f6Smrg        UnlockDisplay (dpy);
5436f03b1f6Smrg        SyncHandle ();
54442941e3bSmrg#ifdef HAVE_SHMAT
5456f03b1f6Smrg	if ( req->shmKey >= 0) {
5466f03b1f6Smrg	    shmdt( (const void *) shMem );
54742941e3bSmrg	}
5486f03b1f6Smrg#endif
5496f03b1f6Smrg        return -1;
5506f03b1f6Smrg    }
55142941e3bSmrg#ifdef HAVE_SHMAT
5526f03b1f6Smrg    shmdt( (const void *) shMem );
5536f03b1f6Smrg#endif
5546f03b1f6Smrg
5556f03b1f6Smrg    if (rep.length > 0) {
5566f03b1f6Smrg
5576f03b1f6Smrg        int realSize = rep.length << 2;
5586f03b1f6Smrg
5596f03b1f6Smrg	tmpBuf = (char *) Xmalloc(realSize);
5606f03b1f6Smrg	if (tmpBuf) {
5616f03b1f6Smrg	    *name = (char *) Xmalloc(rep.nameLen);
5626f03b1f6Smrg	    if (*name) {
5636f03b1f6Smrg		*busID = (char *) Xmalloc(rep.busIDLen);
5646f03b1f6Smrg		if (! *busID) {
5656f03b1f6Smrg		    XFree(*name);
5666f03b1f6Smrg		    XFree(tmpBuf);
5676f03b1f6Smrg		}
5686f03b1f6Smrg	    } else {
5696f03b1f6Smrg		XFree(tmpBuf);
57042941e3bSmrg	    }
5716f03b1f6Smrg	}
5726f03b1f6Smrg
5736f03b1f6Smrg	if (*name && *busID && tmpBuf) {
5746f03b1f6Smrg
5756f03b1f6Smrg	    _XRead(dpy, tmpBuf, realSize);
5766f03b1f6Smrg	    strncpy(*name,tmpBuf,rep.nameLen);
5776f03b1f6Smrg	    strncpy(*busID,tmpBuf+rep.nameLen,rep.busIDLen);
5786f03b1f6Smrg	    XFree(tmpBuf);
5796f03b1f6Smrg
5806f03b1f6Smrg	} else {
5816f03b1f6Smrg
5826f03b1f6Smrg	    _XEatData(dpy, realSize);
5836f03b1f6Smrg	    UnlockDisplay (dpy);
5846f03b1f6Smrg	    SyncHandle ();
5856f03b1f6Smrg	    return -1;
5866f03b1f6Smrg
5876f03b1f6Smrg	}
5886f03b1f6Smrg    }
5896f03b1f6Smrg
5906f03b1f6Smrg    UnlockDisplay (dpy);
5916f03b1f6Smrg    SyncHandle ();
5926f03b1f6Smrg    *major = rep.major;
5936f03b1f6Smrg    *minor = rep.minor;
5946f03b1f6Smrg    *patchLevel = rep.patchLevel;
5956f03b1f6Smrg    *isLocal = (req->shmKey > 0) ? rep.isLocal : 1;
5966f03b1f6Smrg    return (rep.length > 0) ? Success : BadImplementation;
5976f03b1f6Smrg}
5986f03b1f6Smrg
599