XvMC.c revision cc1b55f9
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
21cc1b55f9Smrg#ifndef HAVE__XEATDATAWORDS
22cc1b55f9Smrgstatic inline void _XEatDataWords(Display *dpy, unsigned long n)
23cc1b55f9Smrg{
24cc1b55f9Smrg# ifndef LONG64
25cc1b55f9Smrg    if (n >= (ULONG_MAX >> 2))
26cc1b55f9Smrg        _XIOError(dpy);
27cc1b55f9Smrg# endif
28cc1b55f9Smrg    _XEatData (dpy, n << 2);
29cc1b55f9Smrg}
30cc1b55f9Smrg#endif
31cc1b55f9Smrg
326f03b1f6Smrgstatic XExtensionInfo _xvmc_info_data;
336f03b1f6Smrgstatic XExtensionInfo *xvmc_info = &_xvmc_info_data;
3442941e3bSmrgstatic const char *xvmc_extension_name = XvMCName;
356f03b1f6Smrg
3642941e3bSmrgstatic const char *xvmc_error_list[] =
376f03b1f6Smrg{
386f03b1f6Smrg   "BadContext",
396f03b1f6Smrg   "BadSurface",
406f03b1f6Smrg   "BadSubpicture"
416f03b1f6Smrg};
426f03b1f6Smrg
436f03b1f6Smrgstatic XEXT_GENERATE_CLOSE_DISPLAY (xvmc_close_display, xvmc_info)
446f03b1f6Smrg
456f03b1f6Smrg
466f03b1f6Smrgstatic XEXT_GENERATE_ERROR_STRING (xvmc_error_string, xvmc_extension_name,
476f03b1f6Smrg                                   XvMCNumErrors, xvmc_error_list)
486f03b1f6Smrg
496f03b1f6Smrg
506f03b1f6Smrgstatic XExtensionHooks xvmc_extension_hooks = {
516f03b1f6Smrg    NULL,                               /* create_gc */
526f03b1f6Smrg    NULL,                               /* copy_gc */
536f03b1f6Smrg    NULL,                               /* flush_gc */
546f03b1f6Smrg    NULL,                               /* free_gc */
556f03b1f6Smrg    NULL,                               /* create_font */
566f03b1f6Smrg    NULL,                               /* free_font */
576f03b1f6Smrg    xvmc_close_display,                 /* close_display */
586f03b1f6Smrg    NULL,                               /* wire_to_event */
596f03b1f6Smrg    NULL,                               /* event_to_wire */
606f03b1f6Smrg    NULL,                               /* error */
616f03b1f6Smrg    xvmc_error_string                   /* error_string */
626f03b1f6Smrg};
636f03b1f6Smrg
646f03b1f6Smrgstatic XEXT_GENERATE_FIND_DISPLAY (xvmc_find_display, xvmc_info,
656f03b1f6Smrg                                   xvmc_extension_name,
666f03b1f6Smrg                                   &xvmc_extension_hooks,
676f03b1f6Smrg                                   XvMCNumEvents, NULL)
686f03b1f6Smrg
696f03b1f6SmrgBool XvMCQueryExtension (Display *dpy, int *event_basep, int *error_basep)
706f03b1f6Smrg{
716f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
726f03b1f6Smrg
736f03b1f6Smrg    if (XextHasExtension(info)) {
746f03b1f6Smrg        *event_basep = info->codes->first_event;
756f03b1f6Smrg        *error_basep = info->codes->first_error;
766f03b1f6Smrg        return True;
776f03b1f6Smrg    } else {
786f03b1f6Smrg        return False;
796f03b1f6Smrg    }
806f03b1f6Smrg}
816f03b1f6Smrg
826f03b1f6SmrgStatus XvMCQueryVersion (Display *dpy, int *major, int *minor)
836f03b1f6Smrg{
846f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
856f03b1f6Smrg    xvmcQueryVersionReply rep;
866f03b1f6Smrg    xvmcQueryVersionReq  *req;
876f03b1f6Smrg
886f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
896f03b1f6Smrg
906f03b1f6Smrg    LockDisplay (dpy);
916f03b1f6Smrg    XvMCGetReq (QueryVersion, req);
926f03b1f6Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
936f03b1f6Smrg        UnlockDisplay (dpy);
946f03b1f6Smrg        SyncHandle ();
956f03b1f6Smrg        return BadImplementation;
966f03b1f6Smrg    }
976f03b1f6Smrg    *major = rep.major;
986f03b1f6Smrg    *minor = rep.minor;
996f03b1f6Smrg    UnlockDisplay (dpy);
1006f03b1f6Smrg    SyncHandle ();
1016f03b1f6Smrg    return Success;
1026f03b1f6Smrg}
1036f03b1f6Smrg
1046f03b1f6Smrg
1056f03b1f6SmrgXvMCSurfaceInfo * XvMCListSurfaceTypes(Display *dpy, XvPortID port, int *num)
1066f03b1f6Smrg{
1076f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
1086f03b1f6Smrg    xvmcListSurfaceTypesReply rep;
1096f03b1f6Smrg    xvmcListSurfaceTypesReq  *req;
1106f03b1f6Smrg    XvMCSurfaceInfo *surface_info = NULL;
1116f03b1f6Smrg
1126f03b1f6Smrg    *num = 0;
1136f03b1f6Smrg
1146f03b1f6Smrg    XvMCCheckExtension (dpy, info, NULL);
11542941e3bSmrg
1166f03b1f6Smrg    LockDisplay (dpy);
1176f03b1f6Smrg    XvMCGetReq (ListSurfaceTypes, req);
1186f03b1f6Smrg    req->port = port;
1196f03b1f6Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
1206f03b1f6Smrg        UnlockDisplay (dpy);
1216f03b1f6Smrg        SyncHandle ();
1226f03b1f6Smrg        return NULL;
1236f03b1f6Smrg    }
1246f03b1f6Smrg
1256f03b1f6Smrg    if(rep.num > 0) {
126190694daSmrg        if (rep.num < (INT_MAX / sizeof(XvMCSurfaceInfo)))
127190694daSmrg            surface_info = Xmalloc(rep.num * sizeof(XvMCSurfaceInfo));
1286f03b1f6Smrg
1296f03b1f6Smrg        if(surface_info) {
1306f03b1f6Smrg	    xvmcSurfaceInfo sinfo;
1316f03b1f6Smrg	    int i;
1326f03b1f6Smrg
1336f03b1f6Smrg	    *num = rep.num;
1346f03b1f6Smrg
1356f03b1f6Smrg	    for(i = 0; i < rep.num; i++) {
1366f03b1f6Smrg		_XRead(dpy, (char*)&sinfo, sizeof(xvmcSurfaceInfo));
1376f03b1f6Smrg	       surface_info[i].surface_type_id = sinfo.surface_type_id;
1386f03b1f6Smrg	       surface_info[i].chroma_format = sinfo.chroma_format;
1396f03b1f6Smrg	       surface_info[i].max_width = sinfo.max_width;
1406f03b1f6Smrg	       surface_info[i].max_height = sinfo.max_height;
14142941e3bSmrg	       surface_info[i].subpicture_max_width =
1426f03b1f6Smrg					sinfo.subpicture_max_width;
14342941e3bSmrg	       surface_info[i].subpicture_max_height =
1446f03b1f6Smrg					sinfo.subpicture_max_height;
1456f03b1f6Smrg	       surface_info[i].mc_type = sinfo.mc_type;
1466f03b1f6Smrg	       surface_info[i].flags = sinfo.flags;
1476f03b1f6Smrg	    }
1486f03b1f6Smrg	} else
149cc1b55f9Smrg	   _XEatDataWords(dpy, rep.length);
1506f03b1f6Smrg    }
1516f03b1f6Smrg
1526f03b1f6Smrg    UnlockDisplay (dpy);
1536f03b1f6Smrg    SyncHandle ();
1546f03b1f6Smrg    return surface_info;
1556f03b1f6Smrg}
1566f03b1f6Smrg
1576f03b1f6Smrg
1586f03b1f6SmrgXvImageFormatValues * XvMCListSubpictureTypes (
1596f03b1f6Smrg  Display * dpy,
1606f03b1f6Smrg  XvPortID port,
1616f03b1f6Smrg  int surface_type_id,
1626f03b1f6Smrg  int *count_return
1636f03b1f6Smrg)
1646f03b1f6Smrg{
1656f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
1666f03b1f6Smrg    xvmcListSubpictureTypesReply rep;
1676f03b1f6Smrg    xvmcListSubpictureTypesReq  *req;
1686f03b1f6Smrg    XvImageFormatValues *ret = NULL;
1696f03b1f6Smrg
1706f03b1f6Smrg
1716f03b1f6Smrg    *count_return = 0;
1726f03b1f6Smrg
1736f03b1f6Smrg    XvMCCheckExtension (dpy, info, NULL);
1746f03b1f6Smrg
1756f03b1f6Smrg
1766f03b1f6Smrg    LockDisplay (dpy);
1776f03b1f6Smrg    XvMCGetReq (ListSubpictureTypes, req);
1786f03b1f6Smrg    req->port = port;
1796f03b1f6Smrg    req->surface_type_id = surface_type_id;
1806f03b1f6Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
1816f03b1f6Smrg        UnlockDisplay (dpy);
1826f03b1f6Smrg        SyncHandle ();
1836f03b1f6Smrg        return NULL;
1846f03b1f6Smrg    }
1856f03b1f6Smrg
1866f03b1f6Smrg    if(rep.num > 0) {
187190694daSmrg        if (rep.num < (INT_MAX / sizeof(XvImageFormatValues)))
188190694daSmrg            ret = Xmalloc(rep.num * sizeof(XvImageFormatValues));
1896f03b1f6Smrg
1906f03b1f6Smrg        if(ret) {
1916f03b1f6Smrg            xvImageFormatInfo Info;
1926f03b1f6Smrg            int i;
1936f03b1f6Smrg
1946f03b1f6Smrg            *count_return = rep.num;
1956f03b1f6Smrg
1966f03b1f6Smrg            for(i = 0; i < rep.num; i++) {
1976f03b1f6Smrg              _XRead(dpy, (char*)(&Info), sz_xvImageFormatInfo);
19842941e3bSmrg              ret[i].id = Info.id;
19942941e3bSmrg              ret[i].type = Info.type;
20042941e3bSmrg              ret[i].byte_order = Info.byte_order;
2016f03b1f6Smrg              memcpy(&(ret[i].guid[0]), &(Info.guid[0]), 16);
20242941e3bSmrg              ret[i].bits_per_pixel = Info.bpp;
20342941e3bSmrg              ret[i].format = Info.format;
20442941e3bSmrg              ret[i].num_planes = Info.num_planes;
20542941e3bSmrg              ret[i].depth = Info.depth;
20642941e3bSmrg              ret[i].red_mask = Info.red_mask;
20742941e3bSmrg              ret[i].green_mask = Info.green_mask;
20842941e3bSmrg              ret[i].blue_mask = Info.blue_mask;
20942941e3bSmrg              ret[i].y_sample_bits = Info.y_sample_bits;
21042941e3bSmrg              ret[i].u_sample_bits = Info.u_sample_bits;
2116f03b1f6Smrg              ret[i].v_sample_bits = Info.v_sample_bits;
2126f03b1f6Smrg              ret[i].horz_y_period = Info.horz_y_period;
2136f03b1f6Smrg              ret[i].horz_u_period = Info.horz_u_period;
2146f03b1f6Smrg              ret[i].horz_v_period = Info.horz_v_period;
2156f03b1f6Smrg              ret[i].vert_y_period = Info.vert_y_period;
2166f03b1f6Smrg              ret[i].vert_u_period = Info.vert_u_period;
2176f03b1f6Smrg              ret[i].vert_v_period = Info.vert_v_period;
2186f03b1f6Smrg              memcpy(&(ret[i].component_order[0]), &(Info.comp_order[0]), 32);
2196f03b1f6Smrg              ret[i].scanline_order = Info.scanline_order;
2206f03b1f6Smrg            }
2216f03b1f6Smrg        } else
222cc1b55f9Smrg	   _XEatDataWords(dpy, rep.length);
2236f03b1f6Smrg    }
2246f03b1f6Smrg
2256f03b1f6Smrg    UnlockDisplay (dpy);
2266f03b1f6Smrg    SyncHandle ();
22742941e3bSmrg    return ret;
2286f03b1f6Smrg}
2296f03b1f6Smrg
2306f03b1f6Smrg
23142941e3bSmrg/******************************************************************
2326f03b1f6Smrg   These are intended as a protocol interface to be used by direct
2336f03b1f6Smrg   rendering libraries.  They are not intended to be client viewable
2346f03b1f6Smrg   functions.  These will stay in place until we have a mechanism in
2356f03b1f6Smrg   place similar to that of OpenGL with an libXvMCcore library.
23642941e3bSmrg*******************************************************************/
23742941e3bSmrg
23842941e3bSmrg/*
2396f03b1f6Smrg   _xvmc_create_context -
2406f03b1f6Smrg
2416f03b1f6Smrg   Pass in the context with the surface_type_id, width, height,
2426f03b1f6Smrg   port and flags filled out.  This function will fill out the
2436f03b1f6Smrg   context_id and update the width, height and flags field.
2446f03b1f6Smrg   The server may return implementation-specific information
2456f03b1f6Smrg   back in the priv_data.  The size of that information will
2466f03b1f6Smrg   an array of priv_count CARD32s.  This data is allocated by
2476f03b1f6Smrg   this function.  If returned, the caller is responsible for
2486f03b1f6Smrg   freeing it!  Generally, such information is only returned if
24942941e3bSmrg   an XVMC_DIRECT context was specified.
2506f03b1f6Smrg*/
2516f03b1f6Smrg
2526f03b1f6Smrg
2536f03b1f6SmrgStatus _xvmc_create_context (
2546f03b1f6Smrg    Display *dpy,
2556f03b1f6Smrg    XvMCContext *context,
2566f03b1f6Smrg    int *priv_count,
2576f03b1f6Smrg    CARD32 **priv_data
2586f03b1f6Smrg)
2596f03b1f6Smrg{
2606f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
2616f03b1f6Smrg    xvmcCreateContextReply rep;
2626f03b1f6Smrg    xvmcCreateContextReq  *req;
2636f03b1f6Smrg
2646f03b1f6Smrg    *priv_count = 0;
2656f03b1f6Smrg    *priv_data = NULL;
2666f03b1f6Smrg
2676f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
2686f03b1f6Smrg
2696f03b1f6Smrg    LockDisplay (dpy);
2706f03b1f6Smrg    XvMCGetReq (CreateContext, req);
2716f03b1f6Smrg    context->context_id = XAllocID(dpy);
2726f03b1f6Smrg    req->context_id = context->context_id;
2736f03b1f6Smrg    req->port = context->port;
2746f03b1f6Smrg    req->surface_type_id = context->surface_type_id;
2756f03b1f6Smrg    req->width = context->width;
2766f03b1f6Smrg    req->height = context->height;
2776f03b1f6Smrg    req->flags = context->flags;
2786f03b1f6Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
2796f03b1f6Smrg        UnlockDisplay (dpy);
2806f03b1f6Smrg        SyncHandle ();
2816f03b1f6Smrg        return BadImplementation;
2826f03b1f6Smrg    }
2836f03b1f6Smrg    context->width = rep.width_actual;
2846f03b1f6Smrg    context->height = rep.height_actual;
2856f03b1f6Smrg    context->flags = rep.flags_return;
2866f03b1f6Smrg
2876f03b1f6Smrg    if(rep.length) {
288cc1b55f9Smrg	if (rep.length < (INT_MAX >> 2))
289cc1b55f9Smrg	    *priv_data = Xmalloc(rep.length << 2);
2906f03b1f6Smrg	if(*priv_data) {
2916f03b1f6Smrg            _XRead(dpy, (char*)(*priv_data), rep.length << 2);
2926f03b1f6Smrg	    *priv_count = rep.length;
2936f03b1f6Smrg	} else
294cc1b55f9Smrg	    _XEatDataWords(dpy, rep.length);
2956f03b1f6Smrg    }
2966f03b1f6Smrg
2976f03b1f6Smrg    UnlockDisplay (dpy);
2986f03b1f6Smrg    SyncHandle ();
2996f03b1f6Smrg    return Success;
3006f03b1f6Smrg}
3016f03b1f6Smrg
3026f03b1f6SmrgStatus _xvmc_destroy_context (
3036f03b1f6Smrg    Display *dpy,
3046f03b1f6Smrg    XvMCContext *context
3056f03b1f6Smrg)
3066f03b1f6Smrg{
3076f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
3086f03b1f6Smrg    xvmcDestroyContextReq  *req;
3096f03b1f6Smrg
3106f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
3116f03b1f6Smrg
3126f03b1f6Smrg    LockDisplay (dpy);
3136f03b1f6Smrg    XvMCGetReq (DestroyContext, req);
3146f03b1f6Smrg    req->context_id = context->context_id;
3156f03b1f6Smrg    UnlockDisplay (dpy);
3166f03b1f6Smrg    SyncHandle ();
3176f03b1f6Smrg    return Success;
3186f03b1f6Smrg}
3196f03b1f6Smrg
3206f03b1f6Smrg
3216f03b1f6Smrg/*
3226f03b1f6Smrg   _xvmc_create_surface -
3236f03b1f6Smrg
3246f03b1f6Smrg   Pass the context and this function will fill out all the
32542941e3bSmrg   information in the surface.
3266f03b1f6Smrg   The server may return implementation-specific information
3276f03b1f6Smrg   back in the priv_data.  The size of that information will
3286f03b1f6Smrg   an array of priv_count CARD32s.  This data is allocated by
3296f03b1f6Smrg   this function.  If returned, the caller is responsible for
3306f03b1f6Smrg   freeing it!  Generally, such information is returned only if
3316f03b1f6Smrg   the context was a direct context.
33242941e3bSmrg
3336f03b1f6Smrg*/
3346f03b1f6Smrg
3356f03b1f6SmrgStatus _xvmc_create_surface (
3366f03b1f6Smrg    Display *dpy,
3376f03b1f6Smrg    XvMCContext *context,
3386f03b1f6Smrg    XvMCSurface *surface,
3396f03b1f6Smrg    int *priv_count,
3406f03b1f6Smrg    CARD32 **priv_data
3416f03b1f6Smrg)
3426f03b1f6Smrg{
3436f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
3446f03b1f6Smrg    xvmcCreateSurfaceReply rep;
3456f03b1f6Smrg    xvmcCreateSurfaceReq  *req;
3466f03b1f6Smrg
3476f03b1f6Smrg    *priv_count = 0;
3486f03b1f6Smrg    *priv_data = NULL;
3496f03b1f6Smrg
3506f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
3516f03b1f6Smrg
3526f03b1f6Smrg    LockDisplay (dpy);
3536f03b1f6Smrg    XvMCGetReq (CreateSurface, req);
3546f03b1f6Smrg
3556f03b1f6Smrg    surface->surface_id = XAllocID(dpy);
3566f03b1f6Smrg    surface->context_id = context->context_id;
3576f03b1f6Smrg    surface->surface_type_id = context->surface_type_id;
3586f03b1f6Smrg    surface->width = context->width;
3596f03b1f6Smrg    surface->height = context->height;
3606f03b1f6Smrg
3616f03b1f6Smrg    req->surface_id = surface->surface_id;
3626f03b1f6Smrg    req->context_id = surface->context_id;
3636f03b1f6Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
3646f03b1f6Smrg        UnlockDisplay (dpy);
3656f03b1f6Smrg        SyncHandle ();
3666f03b1f6Smrg        return BadImplementation;
3676f03b1f6Smrg    }
3686f03b1f6Smrg
3696f03b1f6Smrg    if(rep.length) {
370cc1b55f9Smrg        if (rep.length < (INT_MAX >> 2))
371cc1b55f9Smrg            *priv_data = Xmalloc(rep.length << 2);
3726f03b1f6Smrg        if(*priv_data) {
3736f03b1f6Smrg            _XRead(dpy, (char*)(*priv_data), rep.length << 2);
3746f03b1f6Smrg            *priv_count = rep.length;
3756f03b1f6Smrg        } else
376cc1b55f9Smrg            _XEatDataWords(dpy, rep.length);
3776f03b1f6Smrg    }
3786f03b1f6Smrg
3796f03b1f6Smrg    UnlockDisplay (dpy);
3806f03b1f6Smrg    SyncHandle ();
3816f03b1f6Smrg    return Success;
3826f03b1f6Smrg}
3836f03b1f6Smrg
3846f03b1f6SmrgStatus _xvmc_destroy_surface (
3856f03b1f6Smrg    Display *dpy,
3866f03b1f6Smrg    XvMCSurface *surface
3876f03b1f6Smrg)
3886f03b1f6Smrg{
3896f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
3906f03b1f6Smrg    xvmcDestroySurfaceReq  *req;
3916f03b1f6Smrg
3926f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
3936f03b1f6Smrg
3946f03b1f6Smrg    LockDisplay (dpy);
3956f03b1f6Smrg    XvMCGetReq (DestroySurface, req);
3966f03b1f6Smrg    req->surface_id = surface->surface_id;
3976f03b1f6Smrg    UnlockDisplay (dpy);
3986f03b1f6Smrg    SyncHandle ();
3996f03b1f6Smrg    return Success;
4006f03b1f6Smrg}
4016f03b1f6Smrg
4026f03b1f6Smrg/*
4036f03b1f6Smrg   _xvmc_create_subpicture -
4046f03b1f6Smrg
4056f03b1f6Smrg   Pass the subpicture with the width, height and xvimage_id filled
4066f03b1f6Smrg   out and this function will fill out everything else in the
4076f03b1f6Smrg   subpicture as well as adjust the width and height if needed.
4086f03b1f6Smrg   The server may return implementation-specific information
4096f03b1f6Smrg   back in the priv_data.  The size of that information will
4106f03b1f6Smrg   an array of priv_count CARD32s.  This data is allocated by
4116f03b1f6Smrg   this function.  If returned, the caller is responsible for
4126f03b1f6Smrg   freeing it!  Generally, such information is returned only if
4136f03b1f6Smrg   the context was a direct context.
4146f03b1f6Smrg
4156f03b1f6Smrg*/
4166f03b1f6Smrg
4176f03b1f6SmrgStatus _xvmc_create_subpicture (
4186f03b1f6Smrg    Display *dpy,
4196f03b1f6Smrg    XvMCContext *context,
4206f03b1f6Smrg    XvMCSubpicture *subpicture,
4216f03b1f6Smrg    int *priv_count,
4226f03b1f6Smrg    CARD32 **priv_data
4236f03b1f6Smrg)
4246f03b1f6Smrg{
4256f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
4266f03b1f6Smrg    xvmcCreateSubpictureReply rep;
4276f03b1f6Smrg    xvmcCreateSubpictureReq  *req;
4286f03b1f6Smrg
4296f03b1f6Smrg    *priv_count = 0;
4306f03b1f6Smrg    *priv_data = NULL;
4316f03b1f6Smrg
4326f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
4336f03b1f6Smrg
4346f03b1f6Smrg    LockDisplay (dpy);
4356f03b1f6Smrg    XvMCGetReq (CreateSubpicture, req);
4366f03b1f6Smrg
4376f03b1f6Smrg    subpicture->subpicture_id = XAllocID(dpy);
4386f03b1f6Smrg    subpicture->context_id = context->context_id;
4396f03b1f6Smrg
4406f03b1f6Smrg    req->subpicture_id = subpicture->subpicture_id;
4416f03b1f6Smrg    req->context_id = subpicture->context_id;
4426f03b1f6Smrg    req->xvimage_id = subpicture->xvimage_id;
4436f03b1f6Smrg    req->width = subpicture->width;
4446f03b1f6Smrg    req->height = subpicture->height;
4456f03b1f6Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
4466f03b1f6Smrg        UnlockDisplay (dpy);
4476f03b1f6Smrg        SyncHandle ();
4486f03b1f6Smrg        return BadImplementation;
4496f03b1f6Smrg    }
4506f03b1f6Smrg
4516f03b1f6Smrg    subpicture->width = rep.width_actual;
4526f03b1f6Smrg    subpicture->height = rep.height_actual;
4536f03b1f6Smrg    subpicture->num_palette_entries = rep.num_palette_entries;
4546f03b1f6Smrg    subpicture->entry_bytes = rep.entry_bytes;
4556f03b1f6Smrg    subpicture->component_order[0] = rep.component_order[0];
4566f03b1f6Smrg    subpicture->component_order[1] = rep.component_order[1];
4576f03b1f6Smrg    subpicture->component_order[2] = rep.component_order[2];
4586f03b1f6Smrg    subpicture->component_order[3] = rep.component_order[3];
4596f03b1f6Smrg
4606f03b1f6Smrg    if(rep.length) {
461cc1b55f9Smrg        if (rep.length < (INT_MAX >> 2))
462cc1b55f9Smrg            *priv_data = Xmalloc(rep.length << 2);
4636f03b1f6Smrg        if(*priv_data) {
4646f03b1f6Smrg            _XRead(dpy, (char*)(*priv_data), rep.length << 2);
4656f03b1f6Smrg            *priv_count = rep.length;
4666f03b1f6Smrg        } else
467cc1b55f9Smrg            _XEatDataWords(dpy, rep.length);
4686f03b1f6Smrg    }
4696f03b1f6Smrg
4706f03b1f6Smrg    UnlockDisplay (dpy);
4716f03b1f6Smrg    SyncHandle ();
4726f03b1f6Smrg    return Success;
4736f03b1f6Smrg}
4746f03b1f6Smrg
4756f03b1f6SmrgStatus _xvmc_destroy_subpicture(
4766f03b1f6Smrg    Display *dpy,
4776f03b1f6Smrg    XvMCSubpicture *subpicture
4786f03b1f6Smrg)
4796f03b1f6Smrg{
4806f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
4816f03b1f6Smrg    xvmcDestroySubpictureReq  *req;
4826f03b1f6Smrg
4836f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
4846f03b1f6Smrg
4856f03b1f6Smrg    LockDisplay (dpy);
4866f03b1f6Smrg    XvMCGetReq (DestroySubpicture, req);
48742941e3bSmrg    req->subpicture_id = subpicture->subpicture_id;
4886f03b1f6Smrg    UnlockDisplay (dpy);
4896f03b1f6Smrg    SyncHandle ();
4906f03b1f6Smrg    return Success;
4916f03b1f6Smrg}
4926f03b1f6Smrg
4936f03b1f6SmrgStatus XvMCGetDRInfo(Display *dpy, XvPortID port,
49442941e3bSmrg		     char **name, char **busID,
49542941e3bSmrg		     int *major, int *minor,
4966f03b1f6Smrg		     int *patchLevel,
4976f03b1f6Smrg		     int *isLocal)
4986f03b1f6Smrg{
4996f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
5006f03b1f6Smrg    xvmcGetDRInfoReply rep;
5016f03b1f6Smrg    xvmcGetDRInfoReq  *req;
5026f03b1f6Smrg    CARD32 magic;
5036f03b1f6Smrg
50442941e3bSmrg#ifdef HAVE_SHMAT
5056f03b1f6Smrg    volatile CARD32 *shMem;
5066f03b1f6Smrg    struct timezone here;
5076f03b1f6Smrg    struct timeval now;
5086f03b1f6Smrg    here.tz_minuteswest = 0;
5096f03b1f6Smrg    here.tz_dsttime = 0;
5106f03b1f6Smrg#endif
5116f03b1f6Smrg
512190694daSmrg    *name = NULL;
513190694daSmrg    *busID = NULL;
514190694daSmrg
5156f03b1f6Smrg    XvMCCheckExtension (dpy, info, BadImplementation);
5166f03b1f6Smrg
5176f03b1f6Smrg    LockDisplay (dpy);
5186f03b1f6Smrg    XvMCGetReq (GetDRInfo, req);
5196f03b1f6Smrg
5206f03b1f6Smrg    req->port = port;
5216f03b1f6Smrg    magic = 0;
5226f03b1f6Smrg    req->magic = 0;
52342941e3bSmrg#ifdef HAVE_SHMAT
5246f03b1f6Smrg    req->shmKey = shmget(IPC_PRIVATE, 1024, IPC_CREAT | 0600);
5256f03b1f6Smrg
5266f03b1f6Smrg    /*
5276f03b1f6Smrg     * We fill a shared memory page with a repetitive pattern. If the
5286f03b1f6Smrg     * X server can read this pattern, we probably have a local connection.
5296f03b1f6Smrg     * Note that we can trigger the remote X server to read any shared
5306f03b1f6Smrg     * page on the remote machine, so we shouldn't be able to guess and verify
5316f03b1f6Smrg     * any complicated data on those pages. Thats the explanation of this
5326f03b1f6Smrg     * otherwise stupid-looking pattern algorithm.
5336f03b1f6Smrg     */
53442941e3bSmrg
5356f03b1f6Smrg    if (req->shmKey >= 0) {
5366f03b1f6Smrg	shMem = (CARD32 *) shmat(req->shmKey, NULL, 0);
5376f03b1f6Smrg	shmctl( req->shmKey, IPC_RMID, NULL);
53842941e3bSmrg	if ( shMem ) {
5396f03b1f6Smrg
5406f03b1f6Smrg	    register volatile CARD32 *shMemC = shMem;
5416f03b1f6Smrg	    register int i;
5426f03b1f6Smrg
5436f03b1f6Smrg	    gettimeofday( &now, &here);
5446f03b1f6Smrg	    magic = now.tv_usec & 0x000FFFFF;
5456f03b1f6Smrg	    req->magic = magic;
5466f03b1f6Smrg	    i = 1024 / sizeof(CARD32);
5476f03b1f6Smrg	    while(i--) {
54842941e3bSmrg	        *shMemC++ = magic;
5496f03b1f6Smrg	        magic = ~magic;
5506f03b1f6Smrg	    }
5516f03b1f6Smrg	} else {
5526f03b1f6Smrg	    req->shmKey = -1;
5536f03b1f6Smrg	}
5546f03b1f6Smrg    }
5556f03b1f6Smrg#else
5566f03b1f6Smrg    req->shmKey = 0;
5576f03b1f6Smrg#endif
5586f03b1f6Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
5596f03b1f6Smrg        UnlockDisplay (dpy);
5606f03b1f6Smrg        SyncHandle ();
56142941e3bSmrg#ifdef HAVE_SHMAT
5626f03b1f6Smrg	if ( req->shmKey >= 0) {
5636f03b1f6Smrg	    shmdt( (const void *) shMem );
56442941e3bSmrg	}
5656f03b1f6Smrg#endif
5666f03b1f6Smrg        return -1;
5676f03b1f6Smrg    }
56842941e3bSmrg#ifdef HAVE_SHMAT
5696f03b1f6Smrg    shmdt( (const void *) shMem );
5706f03b1f6Smrg#endif
5716f03b1f6Smrg
5726f03b1f6Smrg    if (rep.length > 0) {
573190694daSmrg	unsigned long realSize = 0;
574190694daSmrg	char *tmpBuf = NULL;
575190694daSmrg
576cc1b55f9Smrg	if ((rep.length < (INT_MAX >> 2)) &&
577cc1b55f9Smrg	    /* protect against overflow in strncpy below */
578cc1b55f9Smrg	    (rep.nameLen + rep.busIDLen > rep.nameLen)) {
579190694daSmrg	    realSize = rep.length << 2;
580190694daSmrg	    if (realSize >= (rep.nameLen + rep.busIDLen)) {
581190694daSmrg		tmpBuf = Xmalloc(realSize);
582190694daSmrg		*name = Xmalloc(rep.nameLen);
583190694daSmrg		*busID = Xmalloc(rep.busIDLen);
58442941e3bSmrg	    }
5856f03b1f6Smrg	}
5866f03b1f6Smrg
5876f03b1f6Smrg	if (*name && *busID && tmpBuf) {
5886f03b1f6Smrg	    _XRead(dpy, tmpBuf, realSize);
5896f03b1f6Smrg	    strncpy(*name,tmpBuf,rep.nameLen);
590cc1b55f9Smrg	    (*name)[rep.nameLen - 1] = '\0';
5916f03b1f6Smrg	    strncpy(*busID,tmpBuf+rep.nameLen,rep.busIDLen);
592cc1b55f9Smrg	    (*busID)[rep.busIDLen - 1] = '\0';
5936f03b1f6Smrg	    XFree(tmpBuf);
5946f03b1f6Smrg	} else {
595190694daSmrg	    XFree(*name);
596190694daSmrg	    *name = NULL;
597190694daSmrg	    XFree(*busID);
598cc1b55f9Smrg	    *busID = NULL;
599190694daSmrg	    XFree(tmpBuf);
6006f03b1f6Smrg
601cc1b55f9Smrg	    _XEatDataWords(dpy, rep.length);
6026f03b1f6Smrg	    UnlockDisplay (dpy);
6036f03b1f6Smrg	    SyncHandle ();
6046f03b1f6Smrg	    return -1;
6056f03b1f6Smrg
6066f03b1f6Smrg	}
6076f03b1f6Smrg    }
6086f03b1f6Smrg
6096f03b1f6Smrg    UnlockDisplay (dpy);
6106f03b1f6Smrg    SyncHandle ();
6116f03b1f6Smrg    *major = rep.major;
6126f03b1f6Smrg    *minor = rep.minor;
6136f03b1f6Smrg    *patchLevel = rep.patchLevel;
6146f03b1f6Smrg    *isLocal = (req->shmKey > 0) ? rep.isLocal : 1;
6156f03b1f6Smrg    return (rep.length > 0) ? Success : BadImplementation;
6166f03b1f6Smrg}
6176f03b1f6Smrg
618