From 120c3035f60138ad15599b0b0c4468400e966423 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Sat, 13 Nov 2004 11:09:23 +0000 Subject: lib/XvMC/Imake Added support for automatic loading of the correct hardware XvMC driver. This involves a protocol extension of the XvMC protocol. The XvMC revision number was bumped. --- include/X11/extensions/XvMClib.h | 8 ++- src/XvMC.c | 127 +++++++++++++++++++++++++++++++++++++++ src/XvMCWrapper.c | 127 ++++++++++++++++++++++++++------------- 3 files changed, 220 insertions(+), 42 deletions(-) diff --git a/include/X11/extensions/XvMClib.h b/include/X11/extensions/XvMClib.h index bc8d7cc..b97ae22 100644 --- a/include/X11/extensions/XvMClib.h +++ b/include/X11/extensions/XvMClib.h @@ -1,4 +1,4 @@ -/* $XdotOrg: xc/include/extensions/XvMClib.h,v 1.7 2003/12/18 05:48:06 dawes Exp $ */ +/* $XdotOrg: xc/include/extensions/XvMClib.h,v 1.2 2004/04/23 18:43:06 eich Exp $ */ /* $XFree86: xc/include/extensions/XvMClib.h,v 1.6 2001/11/14 21:54:37 mvojkovi Exp $ */ #ifndef _XVMCLIB_H_ @@ -13,6 +13,12 @@ _XFUNCPROTOBEGIN Bool XvMCQueryExtension (Display *display, int *eventBase, int *errBase); Status XvMCQueryVersion (Display *display, int *major_versionp, int *minor_versionp); +Status XvMCGetDRInfo(Display *dpy, XvPortID port, + char **name, char **busID, + int *major, int *minor, + int *patchLevel, + int *isLocal); + XvMCSurfaceInfo * XvMCListSurfaceTypes(Display *dpy, XvPortID port, int *num); diff --git a/src/XvMC.c b/src/XvMC.c index f63e278..e022ad9 100644 --- a/src/XvMC.c +++ b/src/XvMC.c @@ -4,6 +4,12 @@ #include #include "XvMClibint.h" +#ifdef HAS_SHM +#include +#include +#endif +#include +#include #include #include @@ -465,3 +471,124 @@ Status _xvmc_destroy_subpicture( return Success; } +Status XvMCGetDRInfo(Display *dpy, XvPortID port, + char **name, char **busID, + int *major, int *minor, + int *patchLevel, + int *isLocal) +{ + XExtDisplayInfo *info = xvmc_find_display(dpy); + xvmcGetDRInfoReply rep; + xvmcGetDRInfoReq *req; + char *tmpBuf = NULL; + CARD32 magic; + +#ifdef HAS_SHM + volatile CARD32 *shMem; + struct timezone here; + struct timeval now; + here.tz_minuteswest = 0; + here.tz_dsttime = 0; +#endif + + XvMCCheckExtension (dpy, info, BadImplementation); + + LockDisplay (dpy); + XvMCGetReq (GetDRInfo, req); + + req->port = port; + magic = 0; + req->magic = 0; +#ifdef HAS_SHM + req->shmKey = shmget(IPC_PRIVATE, getpagesize(), IPC_CREAT | 0600); + + /* + * We fill a shared memory page with a repetitive pattern. If the + * X server can read this pattern, we probably have a local connection. + * Note that we can trigger the remote X server to read any shared + * page on the remote machine, so we shouldn't be able to guess and verify + * any complicated data on those pages. Thats the explanation of this + * otherwise stupid-looking pattern algorithm. + */ + + if (req->shmKey >= 0) { + shMem = (CARD32 *) shmat(req->shmKey, 0, 0); + shmctl( req->shmKey, IPC_RMID, 0); + if ( shMem ) { + + register volatile CARD32 *shMemC = shMem; + register int i; + + gettimeofday( &now, &here); + magic = now.tv_usec & 0x000FFFFF; + req->magic = magic; + i = getpagesize() / sizeof(CARD32); + while(i--) { + *shMemC++ = magic; + magic = ~magic; + } + } else { + req->shmKey = -1; + } + } +#else + req->shmKey = 0; +#endif + if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) { + UnlockDisplay (dpy); + SyncHandle (); +#ifdef HAS_SHM + if ( req->shmKey >= 0) { + shmdt( (const void *) shMem ); + } +#endif + return -1; + } +#ifdef HAS_SHM + shmdt( (const void *) shMem ); +#endif + + if (rep.length > 0) { + + int realSize = rep.length << 2; + + tmpBuf = (char *) Xmalloc(realSize); + if (tmpBuf) { + *name = (char *) Xmalloc(rep.nameLen); + if (*name) { + *busID = (char *) Xmalloc(rep.busIDLen); + if (! *busID) { + XFree(*name); + XFree(tmpBuf); + } + } else { + XFree(tmpBuf); + } + } + + if (*name && *busID && tmpBuf) { + + _XRead(dpy, tmpBuf, realSize); + strncpy(*name,tmpBuf,rep.nameLen); + strncpy(*busID,tmpBuf+rep.nameLen,rep.busIDLen); + XFree(tmpBuf); + + } else { + + _XEatData(dpy, realSize); + UnlockDisplay (dpy); + SyncHandle (); + return -1; + + } + } + + UnlockDisplay (dpy); + SyncHandle (); + *major = rep.major; + *minor = rep.minor; + *patchLevel = rep.patchLevel; + *isLocal = (req->shmKey > 0) ? rep.isLocal : 1; + return (rep.length > 0) ? Success : BadImplementation; +} + diff --git a/src/XvMCWrapper.c b/src/XvMCWrapper.c index 77f8df9..86e7fa3 100644 --- a/src/XvMCWrapper.c +++ b/src/XvMCWrapper.c @@ -50,6 +50,7 @@ #include #include #include +#include typedef Bool (*XvMCQueryExtensionP) (Display *, int *, int *); @@ -105,7 +106,8 @@ typedef Status (*XvMCBeginSurfaceP) (Display *,XvMCContext *,XvMCSurface *, typedef Status (*XvMCLoadQMatrixP) (Display *, XvMCContext *,const XvMCQMatrix *); typedef Status (*XvMCPutSliceP)(Display *,XvMCContext *, char *,int); typedef Status (*XvMCPutSlice2P)(Display *,XvMCContext *, char *,int, unsigned); -typedef char * (*XvMCDRIGetClientDriverNameP)(Display *, XvPortID); +typedef Status (*XvMCGetDRInfoP)(Display *, XvPortID, char **, char **, int *, int *, + int *, int *); typedef struct { @@ -150,12 +152,11 @@ typedef struct { XvMCPutSliceP XvMCPutSlice; XvMCPutSlice2P XvMCPutSlice2; - /* * Driver name function. */ - XvMCDRIGetClientDriverNameP XvMCDRIGetClientDriverName; + XvMCGetDRInfoP XvMCGetDRInfo; int preInitialised; int initialised; @@ -192,10 +193,38 @@ static void *handle2; base.pointer = (pointer##P) dlsym((handle),#pointer); \ if (dlerror() != NULL) { \ base.pointer = (pointer##P) dlsym((handle2),#pointer); \ - if (dlerror() != NULL) return; \ + if (dlerror() != NULL) return; \ } +/* + * Try to dlopen a shared library, versionless first. + */ + + +static void *dlopenversion(const char *lib, const char *version, int flag) +{ + void *ret; + int curLen,verLen; + char *curName; + const char *tail; + + + curLen = strlen(lib) + (verLen = strlen(version)) + 1; + curName = (char *) malloc(curLen * sizeof(char)); + strncpy( curName, lib, curLen); + if (verLen > 1) { + if (NULL != (tail = strstr(version+1,"."))) { + strncat( curName, version, tail - version); + } else { + strncat( curName, version, verLen); + } + } + ret = dlopen(curName, flag); + free(curName); + return ret; +} + static int preInitW(Display *dpy) { @@ -208,13 +237,13 @@ static int preInitW(Display *dpy) wrapperPreInit = 1; xW.preInitialised = 0; xW.initialised = 0; - xvhandle = dlopen("libXv.so" XV_SOVERSION, RTLD_LAZY | RTLD_GLOBAL); + xvhandle = dlopenversion("libXv.so", XV_SOVERSION, RTLD_LAZY | RTLD_GLOBAL); if (!xvhandle) { - fprintf(stderr,"XvMCWrapper: Warning! Could not open shared " - "library \"libXv.so" XV_SOVERSION "\"\nThis may cause relocation " - "errors later.\nError was: \"%s\".\n",dlerror()); + fprintf(stderr,"XvMCWrapper: Warning! Could not open shared " + "library \"libXv.so" XV_SOVERSION "\"\nThis may cause relocation " + "errors later.\nError was: \"%s\".\n",dlerror()); } - handle2 = dlopen("libXvMC.so" XVMC_SOVERSION, RTLD_LAZY | RTLD_GLOBAL); + handle2 = dlopenversion("libXvMC.so", XVMC_SOVERSION, RTLD_LAZY | RTLD_GLOBAL); if (!handle2) { fprintf(stderr,"XvMCWrapper: Could not load XvMC " "library \"libXvMC.so" XVMC_SOVERSION "\". Failing\n"); @@ -236,6 +265,8 @@ static void initW(Display *dpy, XvPortID port) char *err; FILE *configFile; int nameLen = 0; + int major,minor,patchLevel,isLocal; + char *busID = NULL; wrapperInit = 1; xW.initialised = 0; @@ -247,45 +278,59 @@ static void initW(Display *dpy, XvPortID port) * Will the DDX tell us the client driver name? */ - xW.XvMCDRIGetClientDriverName = (XvMCDRIGetClientDriverNameP) - dlsym(handle2,"XvMCDRIGetClientDriverName"); + xW.XvMCGetDRInfo = (XvMCGetDRInfoP) + dlsym(handle2,"XvMCGetDRInfo"); + if ((err = dlerror()) == NULL) { - clientName = xW.XvMCDRIGetClientDriverName( dpy, port); - if (clientName) nameLen = strlen(clientName); - } - if (clientName && (nameLen < BUFLEN-7)) { - nameLen += 3; - strncpy(nameBuffer,"lib",BUFLEN-1); - strncpy(nameBuffer+3, clientName, BUFLEN-4); - strncpy(nameBuffer + nameLen, ".so", BUFLEN-nameLen-1); - nameBuffer[BUFLEN-1] = 0; - XFree(clientName); - } else { + if (0 == xW.XvMCGetDRInfo( dpy, port, &clientName, &busID, &major, + &minor,&patchLevel, &isLocal)) { + nameLen = strlen(clientName); + XFree(busID); + if (!isLocal) { + fprintf(stderr,"XvMCWrapper: X server is not local. Cannot run XvMC.\n"); + XFree(clientName); + return; + } + } else { + clientName = NULL; + } + } - /* - * No. Try to obtain it from the config file. - */ + if (clientName && (nameLen < BUFLEN-7) && (nameLen > 0)) { + nameLen += 3; + strncpy(nameBuffer,"lib",BUFLEN-1); + strncpy(nameBuffer+3, clientName, BUFLEN-4); + strncpy(nameBuffer + nameLen, ".so", BUFLEN-nameLen-1); + nameBuffer[BUFLEN-1] = 0; + XFree(clientName); + handle = dlopenversion(nameBuffer, XVMC_SOVERSION,RTLD_LAZY); + } else { + /* + * No. Try to obtain it from the config file. + */ + if (clientName) XFree(clientName); + configFile = fopen(STRS(XVMC_CONFIGDIR) "/XvMCConfig","r"); - xW.initialised = 0; - xW.vldextension = 0; + xW.initialised = 0; + xW.vldextension = 0; - if (0 == configFile) { - fprintf(stderr,"XvMCWrapper: Could not open config file \"%s\".\n", - STRS(XVMC_CONFIGDIR) "/XvMCConfig"); - perror("XvMCWrapper"); - return; - } + if (0 == configFile) { + fprintf(stderr,"XvMCWrapper: Could not open config file \"%s\".\n", + STRS(XVMC_CONFIGDIR) "/XvMCConfig"); + perror("XvMCWrapper"); + return; + } - if (0 == fgets(nameBuffer, BUFLEN, configFile)) { - fclose(configFile); - fprintf(stderr,"XvMCWrapper: Could not read XvMC library name.\n"); - perror("XvMCWrapper"); - return; - } + if (0 == fgets(nameBuffer, BUFLEN, configFile)) { + fclose(configFile); + fprintf(stderr,"XvMCWrapper: Could not read XvMC library name.\n"); + perror("XvMCWrapper"); + return; + } - fclose(configFile); + fclose(configFile); if ((tmp = strlen(nameBuffer)) == 0) { fprintf(stderr,"XvMCWrapper: Zero length XvMC library name.\n"); fprintf(stderr,"%s\n",dlerror()); @@ -303,8 +348,8 @@ static void initW(Display *dpy, XvPortID port) return; } } + handle = dlopen(nameBuffer,RTLD_LAZY); } - handle = dlopen(nameBuffer, RTLD_LAZY); if (!handle) { fprintf(stderr,"XvMCWrapper: Could not load hardware specific XvMC " "library \"%s\".\n",nameBuffer); -- cgit v1.2.3