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
255d8688b9Smrgstatic const char *xvmc_error_list[] = {
265d8688b9Smrg    "BadContext",
275d8688b9Smrg    "BadSurface",
285d8688b9Smrg    "BadSubpicture"
296f03b1f6Smrg};
306f03b1f6Smrg
315d8688b9Smrgstatic XEXT_GENERATE_CLOSE_DISPLAY(xvmc_close_display, xvmc_info)
325d8688b9Smrgstatic XEXT_GENERATE_ERROR_STRING(xvmc_error_string, xvmc_extension_name,
335d8688b9Smrg                                  XvMCNumErrors, xvmc_error_list)
346f03b1f6Smrg
356f03b1f6Smrgstatic XExtensionHooks xvmc_extension_hooks = {
365d8688b9Smrg    NULL,                       /* create_gc */
375d8688b9Smrg    NULL,                       /* copy_gc */
385d8688b9Smrg    NULL,                       /* flush_gc */
395d8688b9Smrg    NULL,                       /* free_gc */
405d8688b9Smrg    NULL,                       /* create_font */
415d8688b9Smrg    NULL,                       /* free_font */
425d8688b9Smrg    xvmc_close_display,         /* close_display */
435d8688b9Smrg    NULL,                       /* wire_to_event */
445d8688b9Smrg    NULL,                       /* event_to_wire */
455d8688b9Smrg    NULL,                       /* error */
465d8688b9Smrg    xvmc_error_string           /* error_string */
476f03b1f6Smrg};
486f03b1f6Smrg
495d8688b9Smrgstatic XEXT_GENERATE_FIND_DISPLAY(xvmc_find_display, xvmc_info,
505d8688b9Smrg                                  xvmc_extension_name,
515d8688b9Smrg                                  &xvmc_extension_hooks,
525d8688b9Smrg                                  XvMCNumEvents, NULL)
536f03b1f6Smrg
545d8688b9SmrgBool
555d8688b9SmrgXvMCQueryExtension(Display *dpy, int *event_basep, int *error_basep)
566f03b1f6Smrg{
576f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
586f03b1f6Smrg
596f03b1f6Smrg    if (XextHasExtension(info)) {
606f03b1f6Smrg        *event_basep = info->codes->first_event;
616f03b1f6Smrg        *error_basep = info->codes->first_error;
626f03b1f6Smrg        return True;
635d8688b9Smrg    }
645d8688b9Smrg    else {
656f03b1f6Smrg        return False;
666f03b1f6Smrg    }
676f03b1f6Smrg}
686f03b1f6Smrg
695d8688b9SmrgStatus
705d8688b9SmrgXvMCQueryVersion(Display *dpy, int *major, int *minor)
716f03b1f6Smrg{
726f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
736f03b1f6Smrg    xvmcQueryVersionReply rep;
745d8688b9Smrg    xvmcQueryVersionReq *req;
756f03b1f6Smrg
765d8688b9Smrg    XvMCCheckExtension(dpy, info, BadImplementation);
776f03b1f6Smrg
785d8688b9Smrg    LockDisplay(dpy);
795d8688b9Smrg    XvMCGetReq(QueryVersion, req);
805d8688b9Smrg    if (!_XReply(dpy, (xReply *) &rep, 0, xTrue)) {
815d8688b9Smrg        UnlockDisplay(dpy);
825d8688b9Smrg        SyncHandle();
836f03b1f6Smrg        return BadImplementation;
846f03b1f6Smrg    }
855d8688b9Smrg    *major = (int) rep.major;
865d8688b9Smrg    *minor = (int) rep.minor;
875d8688b9Smrg    UnlockDisplay(dpy);
885d8688b9Smrg    SyncHandle();
896f03b1f6Smrg    return Success;
906f03b1f6Smrg}
916f03b1f6Smrg
925d8688b9SmrgXvMCSurfaceInfo *
935d8688b9SmrgXvMCListSurfaceTypes(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
1025d8688b9Smrg    XvMCCheckExtension(dpy, info, NULL);
10342941e3bSmrg
1045d8688b9Smrg    LockDisplay(dpy);
1055d8688b9Smrg    XvMCGetReq(ListSurfaceTypes, req);
1065d8688b9Smrg    req->port = (CARD32) port;
1075d8688b9Smrg    if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
1085d8688b9Smrg        UnlockDisplay(dpy);
1095d8688b9Smrg        SyncHandle();
1106f03b1f6Smrg        return NULL;
1116f03b1f6Smrg    }
1126f03b1f6Smrg
1135d8688b9Smrg    if (rep.num > 0) {
114190694daSmrg        if (rep.num < (INT_MAX / sizeof(XvMCSurfaceInfo)))
115190694daSmrg            surface_info = Xmalloc(rep.num * sizeof(XvMCSurfaceInfo));
1166f03b1f6Smrg
1175d8688b9Smrg        if (surface_info) {
1185d8688b9Smrg            *num = (int) rep.num;
1195d8688b9Smrg
1205d8688b9Smrg            for (CARD32 i = 0; i < rep.num; i++) {
1215d8688b9Smrg                xvmcSurfaceInfo sinfo;
1225d8688b9Smrg
1235d8688b9Smrg                _XRead(dpy, (char *) &sinfo, sizeof(xvmcSurfaceInfo));
1245d8688b9Smrg                surface_info[i].surface_type_id = (int) sinfo.surface_type_id;
1255d8688b9Smrg                surface_info[i].chroma_format = sinfo.chroma_format;
1265d8688b9Smrg                surface_info[i].max_width = sinfo.max_width;
1275d8688b9Smrg                surface_info[i].max_height = sinfo.max_height;
1285d8688b9Smrg                surface_info[i].subpicture_max_width =
1295d8688b9Smrg                    sinfo.subpicture_max_width;
1305d8688b9Smrg                surface_info[i].subpicture_max_height =
1315d8688b9Smrg                    sinfo.subpicture_max_height;
1325d8688b9Smrg                surface_info[i].mc_type = (int) sinfo.mc_type;
1335d8688b9Smrg                surface_info[i].flags = (int) sinfo.flags;
1345d8688b9Smrg            }
1355d8688b9Smrg        }
1365d8688b9Smrg        else
1375d8688b9Smrg            _XEatDataWords(dpy, rep.length);
1386f03b1f6Smrg    }
1396f03b1f6Smrg
1405d8688b9Smrg    UnlockDisplay(dpy);
1415d8688b9Smrg    SyncHandle();
1426f03b1f6Smrg    return surface_info;
1436f03b1f6Smrg}
1446f03b1f6Smrg
1455d8688b9SmrgXvImageFormatValues *
1465d8688b9SmrgXvMCListSubpictureTypes(Display *dpy,
1475d8688b9Smrg                        XvPortID port,
1485d8688b9Smrg                        int surface_type_id,
1495d8688b9Smrg                        int *count_return)
1506f03b1f6Smrg{
1516f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
1526f03b1f6Smrg    xvmcListSubpictureTypesReply rep;
1536f03b1f6Smrg    xvmcListSubpictureTypesReq  *req;
1546f03b1f6Smrg    XvImageFormatValues *ret = NULL;
1556f03b1f6Smrg
1566f03b1f6Smrg    *count_return = 0;
1576f03b1f6Smrg
1585d8688b9Smrg    XvMCCheckExtension(dpy, info, NULL);
1596f03b1f6Smrg
1605d8688b9Smrg    LockDisplay(dpy);
1615d8688b9Smrg    XvMCGetReq(ListSubpictureTypes, req);
1625d8688b9Smrg    req->port = (CARD32) port;
1635d8688b9Smrg    req->surface_type_id = (CARD32) surface_type_id;
1645d8688b9Smrg    if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
1655d8688b9Smrg        UnlockDisplay(dpy);
1665d8688b9Smrg        SyncHandle();
1676f03b1f6Smrg        return NULL;
1686f03b1f6Smrg    }
1696f03b1f6Smrg
1705d8688b9Smrg    if (rep.num > 0) {
171190694daSmrg        if (rep.num < (INT_MAX / sizeof(XvImageFormatValues)))
172190694daSmrg            ret = Xmalloc(rep.num * sizeof(XvImageFormatValues));
1736f03b1f6Smrg
1745d8688b9Smrg        if (ret) {
1755d8688b9Smrg            *count_return = (int) rep.num;
1765d8688b9Smrg
1775d8688b9Smrg            for (CARD32 i = 0; i < rep.num; i++) {
1785d8688b9Smrg                xvImageFormatInfo Info;
1795d8688b9Smrg
1805d8688b9Smrg                _XRead(dpy, (char *) (&Info), sz_xvImageFormatInfo);
1815d8688b9Smrg                ret[i].id = (int) Info.id;
1825d8688b9Smrg                ret[i].type = Info.type;
1835d8688b9Smrg                ret[i].byte_order = Info.byte_order;
1845d8688b9Smrg                memcpy(&(ret[i].guid[0]), &(Info.guid[0]), 16);
1855d8688b9Smrg                ret[i].bits_per_pixel = Info.bpp;
1865d8688b9Smrg                ret[i].format = Info.format;
1875d8688b9Smrg                ret[i].num_planes = Info.num_planes;
1885d8688b9Smrg                ret[i].depth = Info.depth;
1895d8688b9Smrg                ret[i].red_mask = Info.red_mask;
1905d8688b9Smrg                ret[i].green_mask = Info.green_mask;
1915d8688b9Smrg                ret[i].blue_mask = Info.blue_mask;
1925d8688b9Smrg                ret[i].y_sample_bits = Info.y_sample_bits;
1935d8688b9Smrg                ret[i].u_sample_bits = Info.u_sample_bits;
1945d8688b9Smrg                ret[i].v_sample_bits = Info.v_sample_bits;
1955d8688b9Smrg                ret[i].horz_y_period = Info.horz_y_period;
1965d8688b9Smrg                ret[i].horz_u_period = Info.horz_u_period;
1975d8688b9Smrg                ret[i].horz_v_period = Info.horz_v_period;
1985d8688b9Smrg                ret[i].vert_y_period = Info.vert_y_period;
1995d8688b9Smrg                ret[i].vert_u_period = Info.vert_u_period;
2005d8688b9Smrg                ret[i].vert_v_period = Info.vert_v_period;
2015d8688b9Smrg                memcpy(&(ret[i].component_order[0]), &(Info.comp_order[0]), 32);
2025d8688b9Smrg                ret[i].scanline_order = Info.scanline_order;
2036f03b1f6Smrg            }
2045d8688b9Smrg        }
2055d8688b9Smrg        else
2065d8688b9Smrg            _XEatDataWords(dpy, rep.length);
2076f03b1f6Smrg    }
2086f03b1f6Smrg
2095d8688b9Smrg    UnlockDisplay(dpy);
2105d8688b9Smrg    SyncHandle();
21142941e3bSmrg    return ret;
2126f03b1f6Smrg}
2136f03b1f6Smrg
21442941e3bSmrg/******************************************************************
2156f03b1f6Smrg   These are intended as a protocol interface to be used by direct
2166f03b1f6Smrg   rendering libraries.  They are not intended to be client viewable
2176f03b1f6Smrg   functions.  These will stay in place until we have a mechanism in
2186f03b1f6Smrg   place similar to that of OpenGL with an libXvMCcore library.
21942941e3bSmrg*******************************************************************/
22042941e3bSmrg
22142941e3bSmrg/*
2226f03b1f6Smrg   _xvmc_create_context -
2236f03b1f6Smrg
2246f03b1f6Smrg   Pass in the context with the surface_type_id, width, height,
2256f03b1f6Smrg   port and flags filled out.  This function will fill out the
2266f03b1f6Smrg   context_id and update the width, height and flags field.
2276f03b1f6Smrg   The server may return implementation-specific information
2286f03b1f6Smrg   back in the priv_data.  The size of that information will
2296f03b1f6Smrg   an array of priv_count CARD32s.  This data is allocated by
2306f03b1f6Smrg   this function.  If returned, the caller is responsible for
2316f03b1f6Smrg   freeing it!  Generally, such information is only returned if
23242941e3bSmrg   an XVMC_DIRECT context was specified.
2336f03b1f6Smrg*/
2346f03b1f6Smrg
2355d8688b9SmrgStatus
2365d8688b9Smrg_xvmc_create_context(Display *dpy,
2375d8688b9Smrg                     XvMCContext *context,
2385d8688b9Smrg                     int *priv_count,
2395d8688b9Smrg                     CARD32 **priv_data)
2406f03b1f6Smrg{
2416f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
2426f03b1f6Smrg    xvmcCreateContextReply rep;
2436f03b1f6Smrg    xvmcCreateContextReq  *req;
2446f03b1f6Smrg
2456f03b1f6Smrg    *priv_count = 0;
2466f03b1f6Smrg    *priv_data = NULL;
2476f03b1f6Smrg
2485d8688b9Smrg    XvMCCheckExtension(dpy, info, BadImplementation);
2496f03b1f6Smrg
2505d8688b9Smrg    LockDisplay(dpy);
2515d8688b9Smrg    XvMCGetReq(CreateContext, req);
2526f03b1f6Smrg    context->context_id = XAllocID(dpy);
2535d8688b9Smrg    req->context_id = (CARD32) context->context_id;
2545d8688b9Smrg    req->port =  (CARD32) context->port;
2555d8688b9Smrg    req->surface_type_id = (CARD32) context->surface_type_id;
2566f03b1f6Smrg    req->width = context->width;
2576f03b1f6Smrg    req->height = context->height;
2585d8688b9Smrg    req->flags = (CARD32) context->flags;
2595d8688b9Smrg    if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
2605d8688b9Smrg        UnlockDisplay(dpy);
2615d8688b9Smrg        SyncHandle();
2626f03b1f6Smrg        return BadImplementation;
2636f03b1f6Smrg    }
2646f03b1f6Smrg    context->width = rep.width_actual;
2656f03b1f6Smrg    context->height = rep.height_actual;
2665d8688b9Smrg    context->flags = (int) rep.flags_return;
2675d8688b9Smrg
2685d8688b9Smrg    if (rep.length) {
2695d8688b9Smrg        if (rep.length < (INT_MAX >> 2))
2705d8688b9Smrg            *priv_data = Xmalloc(rep.length << 2);
2715d8688b9Smrg        if (*priv_data) {
2725d8688b9Smrg            _XRead(dpy, (char *) (*priv_data), rep.length << 2);
2735d8688b9Smrg            *priv_count = (int) rep.length;
2745d8688b9Smrg        }
2755d8688b9Smrg        else
2765d8688b9Smrg            _XEatDataWords(dpy, rep.length);
2776f03b1f6Smrg    }
2786f03b1f6Smrg
2795d8688b9Smrg    UnlockDisplay(dpy);
2805d8688b9Smrg    SyncHandle();
2816f03b1f6Smrg    return Success;
2826f03b1f6Smrg}
2836f03b1f6Smrg
2845d8688b9SmrgStatus
2855d8688b9Smrg_xvmc_destroy_context(Display *dpy, XvMCContext *context)
2866f03b1f6Smrg{
2876f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
2886f03b1f6Smrg    xvmcDestroyContextReq  *req;
2896f03b1f6Smrg
2905d8688b9Smrg    XvMCCheckExtension(dpy, info, BadImplementation);
2916f03b1f6Smrg
2925d8688b9Smrg    LockDisplay(dpy);
2935d8688b9Smrg    XvMCGetReq(DestroyContext, req);
2945d8688b9Smrg    req->context_id = (CARD32) context->context_id;
2955d8688b9Smrg    UnlockDisplay(dpy);
2965d8688b9Smrg    SyncHandle();
2976f03b1f6Smrg    return Success;
2986f03b1f6Smrg}
2996f03b1f6Smrg
3006f03b1f6Smrg/*
3016f03b1f6Smrg   _xvmc_create_surface -
3026f03b1f6Smrg
3036f03b1f6Smrg   Pass the context and this function will fill out all the
30442941e3bSmrg   information in the surface.
3056f03b1f6Smrg   The server may return implementation-specific information
3066f03b1f6Smrg   back in the priv_data.  The size of that information will
3076f03b1f6Smrg   an array of priv_count CARD32s.  This data is allocated by
3086f03b1f6Smrg   this function.  If returned, the caller is responsible for
3096f03b1f6Smrg   freeing it!  Generally, such information is returned only if
3106f03b1f6Smrg   the context was a direct context.
31142941e3bSmrg
3126f03b1f6Smrg*/
3136f03b1f6Smrg
3145d8688b9SmrgStatus
3155d8688b9Smrg_xvmc_create_surface(Display *dpy,
3165d8688b9Smrg                     XvMCContext *context,
3175d8688b9Smrg                     XvMCSurface *surface,
3185d8688b9Smrg                     int *priv_count,
3195d8688b9Smrg                     CARD32 **priv_data)
3206f03b1f6Smrg{
3216f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
3226f03b1f6Smrg    xvmcCreateSurfaceReply rep;
3236f03b1f6Smrg    xvmcCreateSurfaceReq  *req;
3246f03b1f6Smrg
3256f03b1f6Smrg    *priv_count = 0;
3266f03b1f6Smrg    *priv_data = NULL;
3276f03b1f6Smrg
3285d8688b9Smrg    XvMCCheckExtension(dpy, info, BadImplementation);
3296f03b1f6Smrg
3305d8688b9Smrg    LockDisplay(dpy);
3315d8688b9Smrg    XvMCGetReq(CreateSurface, req);
3326f03b1f6Smrg
3336f03b1f6Smrg    surface->surface_id = XAllocID(dpy);
3346f03b1f6Smrg    surface->context_id = context->context_id;
3356f03b1f6Smrg    surface->surface_type_id = context->surface_type_id;
3366f03b1f6Smrg    surface->width = context->width;
3376f03b1f6Smrg    surface->height = context->height;
3386f03b1f6Smrg
3395d8688b9Smrg    req->surface_id = (CARD32) surface->surface_id;
3405d8688b9Smrg    req->context_id = (CARD32) surface->context_id;
3415d8688b9Smrg    if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
3425d8688b9Smrg        UnlockDisplay(dpy);
3435d8688b9Smrg        SyncHandle();
3446f03b1f6Smrg        return BadImplementation;
3456f03b1f6Smrg    }
3466f03b1f6Smrg
3475d8688b9Smrg    if (rep.length) {
348cc1b55f9Smrg        if (rep.length < (INT_MAX >> 2))
349cc1b55f9Smrg            *priv_data = Xmalloc(rep.length << 2);
3505d8688b9Smrg        if (*priv_data) {
3515d8688b9Smrg            _XRead(dpy, (char *) (*priv_data), rep.length << 2);
3525d8688b9Smrg            *priv_count = (int) rep.length;
3535d8688b9Smrg        }
3545d8688b9Smrg        else
355cc1b55f9Smrg            _XEatDataWords(dpy, rep.length);
3566f03b1f6Smrg    }
3576f03b1f6Smrg
3585d8688b9Smrg    UnlockDisplay(dpy);
3595d8688b9Smrg    SyncHandle();
3606f03b1f6Smrg    return Success;
3616f03b1f6Smrg}
3626f03b1f6Smrg
3635d8688b9SmrgStatus
3645d8688b9Smrg_xvmc_destroy_surface(Display *dpy, XvMCSurface *surface)
3656f03b1f6Smrg{
3666f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
3676f03b1f6Smrg    xvmcDestroySurfaceReq  *req;
3686f03b1f6Smrg
3695d8688b9Smrg    XvMCCheckExtension(dpy, info, BadImplementation);
3706f03b1f6Smrg
3715d8688b9Smrg    LockDisplay(dpy);
3725d8688b9Smrg    XvMCGetReq(DestroySurface, req);
3735d8688b9Smrg    req->surface_id = (CARD32) surface->surface_id;
3745d8688b9Smrg    UnlockDisplay(dpy);
3755d8688b9Smrg    SyncHandle();
3766f03b1f6Smrg    return Success;
3776f03b1f6Smrg}
3786f03b1f6Smrg
3796f03b1f6Smrg/*
3806f03b1f6Smrg   _xvmc_create_subpicture -
3816f03b1f6Smrg
3826f03b1f6Smrg   Pass the subpicture with the width, height and xvimage_id filled
3836f03b1f6Smrg   out and this function will fill out everything else in the
3846f03b1f6Smrg   subpicture as well as adjust the width and height if needed.
3856f03b1f6Smrg   The server may return implementation-specific information
3866f03b1f6Smrg   back in the priv_data.  The size of that information will
3876f03b1f6Smrg   an array of priv_count CARD32s.  This data is allocated by
3886f03b1f6Smrg   this function.  If returned, the caller is responsible for
3896f03b1f6Smrg   freeing it!  Generally, such information is returned only if
3906f03b1f6Smrg   the context was a direct context.
3916f03b1f6Smrg
3926f03b1f6Smrg*/
3936f03b1f6Smrg
3945d8688b9SmrgStatus
3955d8688b9Smrg_xvmc_create_subpicture(Display *dpy,
3965d8688b9Smrg                        XvMCContext *context,
3975d8688b9Smrg                        XvMCSubpicture *subpicture,
3985d8688b9Smrg                        int *priv_count,
3995d8688b9Smrg                        CARD32 **priv_data)
4006f03b1f6Smrg{
4016f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
4026f03b1f6Smrg    xvmcCreateSubpictureReply rep;
4036f03b1f6Smrg    xvmcCreateSubpictureReq  *req;
4046f03b1f6Smrg
4056f03b1f6Smrg    *priv_count = 0;
4066f03b1f6Smrg    *priv_data = NULL;
4076f03b1f6Smrg
4085d8688b9Smrg    XvMCCheckExtension(dpy, info, BadImplementation);
4096f03b1f6Smrg
4105d8688b9Smrg    LockDisplay(dpy);
4115d8688b9Smrg    XvMCGetReq(CreateSubpicture, req);
4126f03b1f6Smrg
4136f03b1f6Smrg    subpicture->subpicture_id = XAllocID(dpy);
4146f03b1f6Smrg    subpicture->context_id = context->context_id;
4156f03b1f6Smrg
4165d8688b9Smrg    req->subpicture_id = (CARD32) subpicture->subpicture_id;
4175d8688b9Smrg    req->context_id = (CARD32) subpicture->context_id;
4185d8688b9Smrg    req->xvimage_id = (CARD32) subpicture->xvimage_id;
4196f03b1f6Smrg    req->width = subpicture->width;
4206f03b1f6Smrg    req->height = subpicture->height;
4215d8688b9Smrg    if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
4225d8688b9Smrg        UnlockDisplay(dpy);
4235d8688b9Smrg        SyncHandle();
4246f03b1f6Smrg        return BadImplementation;
4256f03b1f6Smrg    }
4266f03b1f6Smrg
4276f03b1f6Smrg    subpicture->width = rep.width_actual;
4286f03b1f6Smrg    subpicture->height = rep.height_actual;
4296f03b1f6Smrg    subpicture->num_palette_entries = rep.num_palette_entries;
4306f03b1f6Smrg    subpicture->entry_bytes = rep.entry_bytes;
4315d8688b9Smrg    subpicture->component_order[0] = (char) rep.component_order[0];
4325d8688b9Smrg    subpicture->component_order[1] = (char) rep.component_order[1];
4335d8688b9Smrg    subpicture->component_order[2] = (char) rep.component_order[2];
4345d8688b9Smrg    subpicture->component_order[3] = (char) rep.component_order[3];
4356f03b1f6Smrg
4365d8688b9Smrg    if (rep.length) {
437cc1b55f9Smrg        if (rep.length < (INT_MAX >> 2))
438cc1b55f9Smrg            *priv_data = Xmalloc(rep.length << 2);
4395d8688b9Smrg        if (*priv_data) {
4405d8688b9Smrg            _XRead(dpy, (char *) (*priv_data), rep.length << 2);
4415d8688b9Smrg            *priv_count = (int) rep.length;
4425d8688b9Smrg        }
4435d8688b9Smrg        else
444cc1b55f9Smrg            _XEatDataWords(dpy, rep.length);
4456f03b1f6Smrg    }
4466f03b1f6Smrg
4475d8688b9Smrg    UnlockDisplay(dpy);
4485d8688b9Smrg    SyncHandle();
4496f03b1f6Smrg    return Success;
4506f03b1f6Smrg}
4516f03b1f6Smrg
4525d8688b9SmrgStatus
4535d8688b9Smrg_xvmc_destroy_subpicture(Display *dpy, XvMCSubpicture *subpicture)
4546f03b1f6Smrg{
4556f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
4566f03b1f6Smrg    xvmcDestroySubpictureReq  *req;
4576f03b1f6Smrg
4585d8688b9Smrg    XvMCCheckExtension(dpy, info, BadImplementation);
4596f03b1f6Smrg
4605d8688b9Smrg    LockDisplay(dpy);
4615d8688b9Smrg    XvMCGetReq(DestroySubpicture, req);
4625d8688b9Smrg    req->subpicture_id = (CARD32) subpicture->subpicture_id;
4635d8688b9Smrg    UnlockDisplay(dpy);
4645d8688b9Smrg    SyncHandle();
4656f03b1f6Smrg    return Success;
4666f03b1f6Smrg}
4676f03b1f6Smrg
4685d8688b9SmrgStatus
4695d8688b9SmrgXvMCGetDRInfo(Display *dpy, XvPortID port,
4705d8688b9Smrg              char **name, char **busID,
4715d8688b9Smrg              int *major, int *minor,
4725d8688b9Smrg              int *patchLevel,
4735d8688b9Smrg              int *isLocal)
4746f03b1f6Smrg{
4756f03b1f6Smrg    XExtDisplayInfo *info = xvmc_find_display(dpy);
4766f03b1f6Smrg    xvmcGetDRInfoReply rep;
4776f03b1f6Smrg    xvmcGetDRInfoReq  *req;
4786f03b1f6Smrg
47942941e3bSmrg#ifdef HAVE_SHMAT
4807448d6e9Smrg    int shmKey;
4816f03b1f6Smrg    volatile CARD32 *shMem;
4826f03b1f6Smrg#endif
4836f03b1f6Smrg
484190694daSmrg    *name = NULL;
485190694daSmrg    *busID = NULL;
486190694daSmrg
4875d8688b9Smrg    XvMCCheckExtension(dpy, info, BadImplementation);
4886f03b1f6Smrg
4895d8688b9Smrg    LockDisplay(dpy);
4905d8688b9Smrg    XvMCGetReq(GetDRInfo, req);
4916f03b1f6Smrg
4925d8688b9Smrg    req->port = (CARD32) port;
4936f03b1f6Smrg    req->magic = 0;
49442941e3bSmrg#ifdef HAVE_SHMAT
4957448d6e9Smrg    shmKey = shmget(IPC_PRIVATE, 1024, IPC_CREAT | 0600);
4967448d6e9Smrg    req->shmKey = (CARD32) shmKey;
4976f03b1f6Smrg
4986f03b1f6Smrg    /*
4996f03b1f6Smrg     * We fill a shared memory page with a repetitive pattern. If the
5006f03b1f6Smrg     * X server can read this pattern, we probably have a local connection.
5016f03b1f6Smrg     * Note that we can trigger the remote X server to read any shared
5026f03b1f6Smrg     * page on the remote machine, so we shouldn't be able to guess and verify
5034e5182b7Smrg     * any complicated data on those pages. That's the explanation of this
5046f03b1f6Smrg     * otherwise stupid-looking pattern algorithm.
5056f03b1f6Smrg     */
50642941e3bSmrg
5077448d6e9Smrg    if (shmKey >= 0) {
5085d8688b9Smrg        shMem = (CARD32 *) shmat(shmKey, NULL, 0);
5095d8688b9Smrg        shmctl(shmKey, IPC_RMID, NULL);
5105d8688b9Smrg        if (shMem != (void *) -1) {
5115d8688b9Smrg
5125d8688b9Smrg            register volatile CARD32 *shMemC = shMem;
5135d8688b9Smrg            register int i;
5145d8688b9Smrg            CARD32 magic;
5155d8688b9Smrg            struct timezone here = {0, 0};
5165d8688b9Smrg            struct timeval now;
5175d8688b9Smrg
5185d8688b9Smrg            gettimeofday(&now, &here);
5195d8688b9Smrg            magic = now.tv_usec & 0x000FFFFF;
5205d8688b9Smrg            req->magic = magic;
5215d8688b9Smrg            i = 1024 / sizeof(CARD32);
5225d8688b9Smrg            while (i--) {
5235d8688b9Smrg                *shMemC++ = magic;
5245d8688b9Smrg                magic = ~magic;
5255d8688b9Smrg            }
5265d8688b9Smrg        }
5275d8688b9Smrg        else {
5285d8688b9Smrg            req->shmKey = (CARD32) -1;
5295d8688b9Smrg            shmKey = -1;
5305d8688b9Smrg        }
5316f03b1f6Smrg    }
5326f03b1f6Smrg#else
5336f03b1f6Smrg    req->shmKey = 0;
5346f03b1f6Smrg#endif
5355d8688b9Smrg    if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
5365d8688b9Smrg        UnlockDisplay(dpy);
5375d8688b9Smrg        SyncHandle();
53842941e3bSmrg#ifdef HAVE_SHMAT
5395d8688b9Smrg        if (shmKey >= 0) {
5405d8688b9Smrg            shmdt((const void *) shMem);
5415d8688b9Smrg        }
5426f03b1f6Smrg#endif
5436f03b1f6Smrg        return -1;
5446f03b1f6Smrg    }
54542941e3bSmrg#ifdef HAVE_SHMAT
5467448d6e9Smrg    if (shmKey >= 0) {
5475d8688b9Smrg        shmdt((const void *) shMem);
5487448d6e9Smrg    }
5496f03b1f6Smrg#endif
5506f03b1f6Smrg
5516f03b1f6Smrg    if (rep.length > 0) {
5525d8688b9Smrg        unsigned long realSize = 0;
5535d8688b9Smrg        char *tmpBuf = NULL;
5545d8688b9Smrg
5555d8688b9Smrg        if ((rep.length < (INT_MAX >> 2)) &&
5565d8688b9Smrg            /* protect against overflow in strncpy below */
5575d8688b9Smrg            (rep.nameLen + rep.busIDLen > rep.nameLen)) {
5585d8688b9Smrg            realSize = rep.length << 2;
5595d8688b9Smrg            if (realSize >= (rep.nameLen + rep.busIDLen)) {
5605d8688b9Smrg                tmpBuf = Xmalloc(realSize);
5615d8688b9Smrg                *name = Xmalloc(rep.nameLen);
5625d8688b9Smrg                *busID = Xmalloc(rep.busIDLen);
5635d8688b9Smrg            }
5645d8688b9Smrg        }
5655d8688b9Smrg
5665d8688b9Smrg        if (*name && *busID && tmpBuf) {
5675d8688b9Smrg            _XRead(dpy, tmpBuf, (long) realSize);
5685d8688b9Smrg            strncpy(*name, tmpBuf, rep.nameLen);
5695d8688b9Smrg            (*name)[rep.nameLen == 0 ? 0 : rep.nameLen - 1] = '\0';
5705d8688b9Smrg            strncpy(*busID, tmpBuf + rep.nameLen, rep.busIDLen);
5715d8688b9Smrg            (*busID)[rep.busIDLen == 0 ? 0 : rep.busIDLen - 1] = '\0';
5725d8688b9Smrg            XFree(tmpBuf);
5735d8688b9Smrg        }
5745d8688b9Smrg        else {
5755d8688b9Smrg            XFree(*name);
5765d8688b9Smrg            *name = NULL;
5775d8688b9Smrg            XFree(*busID);
5785d8688b9Smrg            *busID = NULL;
5795d8688b9Smrg            XFree(tmpBuf);
5805d8688b9Smrg
5815d8688b9Smrg            _XEatDataWords(dpy, rep.length);
5825d8688b9Smrg            UnlockDisplay(dpy);
5835d8688b9Smrg            SyncHandle();
5845d8688b9Smrg            return -1;
5855d8688b9Smrg
5865d8688b9Smrg        }
5876f03b1f6Smrg    }
5886f03b1f6Smrg
5895d8688b9Smrg    UnlockDisplay(dpy);
5905d8688b9Smrg    SyncHandle();
5915d8688b9Smrg    *major = (int) rep.major;
5925d8688b9Smrg    *minor = (int) rep.minor;
5935d8688b9Smrg    *patchLevel = (int) rep.patchLevel;
5947448d6e9Smrg#ifdef HAVE_SHMAT
5957448d6e9Smrg    if (shmKey >= 0)
5965d8688b9Smrg        *isLocal = (int) rep.isLocal;
5977448d6e9Smrg    else
5987448d6e9Smrg#endif
5997448d6e9Smrg        *isLocal = 1;
6006f03b1f6Smrg    return (rep.length > 0) ? Success : BadImplementation;
6016f03b1f6Smrg}
602