summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Hellstrom <unichrome@shipmail.org>2004-11-13 11:09:23 +0000
committerThomas Hellstrom <unichrome@shipmail.org>2004-11-13 11:09:23 +0000
commit120c3035f60138ad15599b0b0c4468400e966423 (patch)
tree3c7629856e70c877689e7cb158bfcc9eb8c7bcd5 /src
parent0077c785f91a80d48216a969757bc3f3b607e7e2 (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.c127
-rw-r--r--src/XvMCWrapper.c127
2 files changed, 213 insertions, 41 deletions
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 <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);