diff options
author | Thomas Hellstrom <unichrome@shipmail.org> | 2004-11-13 11:09:23 +0000 |
---|---|---|
committer | Thomas Hellstrom <unichrome@shipmail.org> | 2004-11-13 11:09:23 +0000 |
commit | 120c3035f60138ad15599b0b0c4468400e966423 (patch) | |
tree | 3c7629856e70c877689e7cb158bfcc9eb8c7bcd5 /src | |
parent | 0077c785f91a80d48216a969757bc3f3b607e7e2 (diff) |
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.
Diffstat (limited to 'src')
-rw-r--r-- | src/XvMC.c | 127 | ||||
-rw-r--r-- | src/XvMCWrapper.c | 127 |
2 files changed, 213 insertions, 41 deletions
@@ -4,6 +4,12 @@ #include <stdio.h> #include "XvMClibint.h" +#ifdef HAS_SHM +#include <sys/ipc.h> +#include <sys/shm.h> +#endif +#include <unistd.h> +#include <sys/time.h> #include <X11/extensions/Xext.h> #include <X11/extensions/extutil.h> @@ -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 <stdio.h> #include <string.h> #include <ctype.h> +#include <stdlib.h> 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); |