winex11: Load the XVidMode extension (libXxf86vm) when available.

Francois Gouget fgouget at codeweavers.com
Thu Jun 26 07:02:17 CDT 2008


---

On Debian 4.0 (and other Linux distributions I guess), the static 
version of libXxf86vm is not available. This means that winex11.drv is 
statically linked with libXxf86vm.so. This means the resulting binary 
cannot run on Linux distributions that don't have it, like Debian 3.1.
Loading libXxf86vm.so at runtime like the other X11 extensions solves 
this problem.

 configure                      |   79 ++++++++++++++++++++++++++++++++++++-
 configure.ac                   |    9 ++--
 dlls/winex11.drv/x11drv_main.c |    2 +-
 dlls/winex11.drv/xvidmode.c    |   85 +++++++++++++++++++++++++++++++++-------
 include/config.h.in            |    3 +
 5 files changed, 156 insertions(+), 22 deletions(-)

diff --git a/configure b/configure
index e855076..c47b723 100755
--- a/configure
+++ b/configure
@@ -10088,7 +10088,82 @@ fi
 
                 if test "$ac_cv_header_X11_extensions_xf86vmode_h" = "yes"
         then
-                { echo "$as_me:$LINENO: checking for XF86VidModeQueryExtension in -lXxf86vm" >&5
+            { echo "$as_me:$LINENO: checking for -lXxf86vm" >&5
+echo $ECHO_N "checking for -lXxf86vm... $ECHO_C" >&6; }
+if test "${ac_cv_lib_soname_Xxf86vm+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_soname_save_LIBS=$LIBS
+LIBS="-lXxf86vm $X_LIBS -lXext -lX11 $X_EXTRA_LIBS $LIBS"
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char XF86VidModeQueryExtension ();
+int
+main ()
+{
+return XF86VidModeQueryExtension ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  case "$LIBEXT" in
+    dll) ;;
+    dylib) ac_cv_lib_soname_Xxf86vm=`otool -L conftest$ac_exeext | grep "libXxf86vm\\.[0-9A-Za-z.]*dylib" | sed -e "s/^.*\/\(libXxf86vm\.[0-9A-Za-z.]*dylib\).*$/\1/"';2,$d'` ;;
+    *) ac_cv_lib_soname_Xxf86vm=`$ac_cv_path_LDD conftest$ac_exeext | grep "libXxf86vm\\.$LIBEXT" | sed -e "s/^.*\(libXxf86vm\.$LIBEXT[^	 ]*\).*$/\1/"';2,$d'` ;;
+  esac
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+  LIBS=$ac_check_soname_save_LIBS
+fi
+if test "x$ac_cv_lib_soname_Xxf86vm" = "x"; then
+  { echo "$as_me:$LINENO: result: not found" >&5
+echo "${ECHO_T}not found" >&6; }
+
+else
+  { echo "$as_me:$LINENO: result: $ac_cv_lib_soname_Xxf86vm" >&5
+echo "${ECHO_T}$ac_cv_lib_soname_Xxf86vm" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define SONAME_LIBXXF86VM "$ac_cv_lib_soname_Xxf86vm"
+_ACEOF
+
+       { echo "$as_me:$LINENO: checking for XF86VidModeQueryExtension in -lXxf86vm" >&5
 echo $ECHO_N "checking for XF86VidModeQueryExtension in -lXxf86vm... $ECHO_C" >&6; }
 if test "${ac_cv_lib_Xxf86vm_XF86VidModeQueryExtension+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -10155,7 +10230,7 @@ cat >>confdefs.h <<\_ACEOF
 #define HAVE_LIBXXF86VM 1
 _ACEOF
 
-                     X_PRE_LIBS="$X_PRE_LIBS -lXxf86vm"
+fi
 
 fi
 
diff --git a/configure.ac b/configure.ac
index 77287de..2d2f892 100644
--- a/configure.ac
+++ b/configure.ac
@@ -651,11 +651,10 @@ then
         dnl *** Check for XFree86 VMODE extension
         if test "$ac_cv_header_X11_extensions_xf86vmode_h" = "yes"
         then
-                AC_CHECK_LIB(Xxf86vm, XF86VidModeQueryExtension,
-                  [ AC_DEFINE(HAVE_LIBXXF86VM, 1, [Define if you have the Xxf86vm library])
-                     X_PRE_LIBS="$X_PRE_LIBS -lXxf86vm"
-                  ],,
-                  $X_LIBS -lXext -lX11 $X_EXTRA_LIBS)
+            WINE_CHECK_SONAME(Xxf86vm,XF86VidModeQueryExtension,
+              [AC_CHECK_LIB(Xxf86vm, XF86VidModeQueryExtension,
+                  [ AC_DEFINE(HAVE_LIBXXF86VM, 1, [Define if you have the Xxf86vm library])],,
+                  [$X_LIBS -lXext -lX11 $X_EXTRA_LIBS])],,[$X_LIBS -lXext -lX11 $X_EXTRA_LIBS])
         fi
         WINE_NOTICE_WITH(xvidmode,[test "$ac_cv_lib_Xxf86vm_XF86VidModeQueryExtension" != "yes"],
                          [libXxf86vm development files not found, XFree86 Vidmode won't be supported.])
diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c
index 4ca1bb6..5a2e870 100644
--- a/dlls/winex11.drv/x11drv_main.c
+++ b/dlls/winex11.drv/x11drv_main.c
@@ -525,7 +525,7 @@ static BOOL process_attach(void)
     xinerama_init( WidthOfScreen(screen), HeightOfScreen(screen) );
     X11DRV_Settings_Init();
 
-#ifdef HAVE_LIBXXF86VM
+#ifdef SONAME_LIBXXF86VM
     /* initialize XVidMode */
     X11DRV_XF86VM_Init();
 #endif
diff --git a/dlls/winex11.drv/xvidmode.c b/dlls/winex11.drv/xvidmode.c
index 2c963d6..ea8c38e 100644
--- a/dlls/winex11.drv/xvidmode.c
+++ b/dlls/winex11.drv/xvidmode.c
@@ -19,6 +19,8 @@
  */
 
 #include "config.h"
+#include "wine/port.h"
+
 #include <string.h>
 #include <stdio.h>
 #include <math.h>
@@ -35,10 +37,11 @@
 #include "wingdi.h"
 #include "ddrawi.h"
 #include "wine/debug.h"
+#include "wine/library.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(xvidmode);
 
-#ifdef HAVE_LIBXXF86VM
+#ifdef SONAME_LIBXXF86VM
 
 extern int usexvidmode;
 
@@ -54,6 +57,24 @@ static unsigned int dd_mode_count;
 static XF86VidModeModeInfo** real_xf86vm_modes;
 static unsigned int real_xf86vm_mode_count;
 
+#define MAKE_FUNCPTR(f) typeof(f) * p##f;
+MAKE_FUNCPTR(XF86VidModeGetAllModeLines)
+MAKE_FUNCPTR(XF86VidModeGetGamma)
+MAKE_FUNCPTR(XF86VidModeGetGammaRamp)
+MAKE_FUNCPTR(XF86VidModeGetGammaRampSize)
+MAKE_FUNCPTR(XF86VidModeGetModeLine)
+MAKE_FUNCPTR(XF86VidModeLockModeSwitch)
+MAKE_FUNCPTR(XF86VidModeQueryExtension)
+MAKE_FUNCPTR(XF86VidModeQueryVersion)
+MAKE_FUNCPTR(XF86VidModeSetGamma)
+#ifdef X_XF86VidModeSetGammaRamp
+MAKE_FUNCPTR(XF86VidModeSetGammaRamp)
+#endif /* X_XF86VidModeSetGammaRamp */
+MAKE_FUNCPTR(XF86VidModeSetViewPort)
+MAKE_FUNCPTR(XF86VidModeSwitchToMode)
+#undef MAKE_FUNCPTR
+
+
 static void convert_modeinfo( const XF86VidModeModeInfo *mode)
 {
   int rate;
@@ -98,7 +119,7 @@ static int X11DRV_XF86VM_GetCurrentMode(void)
 
   TRACE("Querying XVidMode current mode\n");
   wine_tsx11_lock();
-  XF86VidModeGetModeLine(gdi_display, DefaultScreen(gdi_display), &dotclock, &line);
+  pXF86VidModeGetModeLine(gdi_display, DefaultScreen(gdi_display), &dotclock, &line);
   wine_tsx11_unlock();
   convert_modeline(dotclock, &line, &cmode, dwBpp);
   for (i=0; i<dd_mode_count; i++)
@@ -123,9 +144,9 @@ static LONG X11DRV_XF86VM_SetCurrentMode(int mode)
   wine_tsx11_lock();
   TRACE("Resizing X display to %dx%d\n", 
         real_xf86vm_modes[mode]->hdisplay, real_xf86vm_modes[mode]->vdisplay);
-  XF86VidModeSwitchToMode(gdi_display, DefaultScreen(gdi_display), real_xf86vm_modes[mode]);
+  pXF86VidModeSwitchToMode(gdi_display, DefaultScreen(gdi_display), real_xf86vm_modes[mode]);
 #if 0 /* it is said that SetViewPort causes problems with some X servers */
-  XF86VidModeSetViewPort(gdi_display, DefaultScreen(gdi_display), 0, 0);
+  pXF86VidModeSetViewPort(gdi_display, DefaultScreen(gdi_display), 0, 0);
 #else
   XWarpPointer(gdi_display, None, DefaultRootWindow(gdi_display), 0, 0, 0, 0, 0, 0);
 #endif
@@ -135,21 +156,50 @@ static LONG X11DRV_XF86VM_SetCurrentMode(int mode)
   return DISP_CHANGE_SUCCESSFUL;
 }
 
+
 void X11DRV_XF86VM_Init(void)
 {
+  void *xvidmode_handle;
   Bool ok;
   int nmodes;
   unsigned int i;
 
   if (xf86vm_major) return; /* already initialized? */
 
+  xvidmode_handle = wine_dlopen(SONAME_LIBXXF86VM, RTLD_NOW, NULL, 0);
+  if (!xvidmode_handle)
+  {
+    TRACE("Unable to open %s, XVidMode disabled\n", SONAME_LIBXXF86VM);
+    usexvidmode = 0;
+    return;
+  }
+
+#define LOAD_FUNCPTR(f) \
+    if((p##f = wine_dlsym(xvidmode_handle, #f, NULL, 0)) == NULL) \
+        goto sym_not_found;
+    LOAD_FUNCPTR(XF86VidModeGetAllModeLines)
+    LOAD_FUNCPTR(XF86VidModeGetGamma)
+    LOAD_FUNCPTR(XF86VidModeGetGammaRamp)
+    LOAD_FUNCPTR(XF86VidModeGetGammaRampSize)
+    LOAD_FUNCPTR(XF86VidModeGetModeLine)
+    LOAD_FUNCPTR(XF86VidModeLockModeSwitch)
+    LOAD_FUNCPTR(XF86VidModeQueryExtension)
+    LOAD_FUNCPTR(XF86VidModeQueryVersion)
+    LOAD_FUNCPTR(XF86VidModeSetGamma)
+#ifdef X_XF86VidModeSetGammaRamp
+    LOAD_FUNCPTR(XF86VidModeSetGammaRamp)
+#endif /* X_XF86VidModeSetGammaRamp */
+    LOAD_FUNCPTR(XF86VidModeSetViewPort)
+    LOAD_FUNCPTR(XF86VidModeSwitchToMode)
+#undef LOAD_FUNCPTR
+
   /* see if XVidMode is available */
   wine_tsx11_lock();
-  ok = XF86VidModeQueryExtension(gdi_display, &xf86vm_event, &xf86vm_error);
+  ok = pXF86VidModeQueryExtension(gdi_display, &xf86vm_event, &xf86vm_error);
   if (ok)
   {
       X11DRV_expect_error(gdi_display, XVidModeErrorHandler, NULL);
-      ok = XF86VidModeQueryVersion(gdi_display, &xf86vm_major, &xf86vm_minor);
+      ok = pXF86VidModeQueryVersion(gdi_display, &xf86vm_major, &xf86vm_minor);
       if (X11DRV_check_error()) ok = FALSE;
   }
   if (ok)
@@ -157,7 +207,7 @@ void X11DRV_XF86VM_Init(void)
 #ifdef X_XF86VidModeSetGammaRamp
       if (xf86vm_major > 2 || (xf86vm_major == 2 && xf86vm_minor >= 1))
       {
-          XF86VidModeGetGammaRampSize(gdi_display, DefaultScreen(gdi_display),
+          pXF86VidModeGetGammaRampSize(gdi_display, DefaultScreen(gdi_display),
                                       &xf86vm_gammaramp_size);
           if (xf86vm_gammaramp_size == 256)
               xf86vm_use_gammaramp = TRUE;
@@ -166,7 +216,7 @@ void X11DRV_XF86VM_Init(void)
 
       /* retrieve modes */
       if (usexvidmode && root_window == DefaultRootWindow( gdi_display ))
-          ok = XF86VidModeGetAllModeLines(gdi_display, DefaultScreen(gdi_display), &nmodes, &real_xf86vm_modes);
+          ok = pXF86VidModeGetAllModeLines(gdi_display, DefaultScreen(gdi_display), &nmodes, &real_xf86vm_modes);
       else
           ok = FALSE; /* In desktop mode, do not switch resolution... But still use the Gamma ramp stuff */
   }
@@ -193,6 +243,13 @@ void X11DRV_XF86VM_Init(void)
 
   TRACE("Available DD modes: count=%d\n", dd_mode_count);
   TRACE("Enabling XVidMode\n");
+  return;
+
+sym_not_found:
+    TRACE("Unable to load function pointers from %s, XVidMode disabled\n", SONAME_LIBXXF86VM);
+    wine_dlclose(xvidmode_handle, NULL, 0);
+    xvidmode_handle = NULL;
+    usexvidmode = 0;
 }
 
 void X11DRV_XF86VM_Cleanup(void)
@@ -207,7 +264,7 @@ void X11DRV_XF86VM_SetExclusiveMode(int lock)
   if (!dd_modes) return; /* no XVidMode */
 
   wine_tsx11_lock();
-  XF86VidModeLockModeSwitch(gdi_display, DefaultScreen(gdi_display), lock);
+  pXF86VidModeLockModeSwitch(gdi_display, DefaultScreen(gdi_display), lock);
   wine_tsx11_unlock();
 }
 
@@ -307,7 +364,7 @@ BOOL X11DRV_XF86VM_GetGammaRamp(LPDDGAMMARAMP ramp)
   {
       Bool ret;
       wine_tsx11_lock();
-      ret = XF86VidModeGetGammaRamp(gdi_display, DefaultScreen(gdi_display), 256,
+      ret = pXF86VidModeGetGammaRamp(gdi_display, DefaultScreen(gdi_display), 256,
 				    ramp->red, ramp->green, ramp->blue);
       wine_tsx11_unlock();
       return ret;
@@ -316,7 +373,7 @@ BOOL X11DRV_XF86VM_GetGammaRamp(LPDDGAMMARAMP ramp)
   else
   {
       wine_tsx11_lock();
-      ret = XF86VidModeGetGamma(gdi_display, DefaultScreen(gdi_display), &gamma);
+      ret = pXF86VidModeGetGamma(gdi_display, DefaultScreen(gdi_display), &gamma);
       wine_tsx11_unlock();
       if (ret) {
 	  GenerateRampFromGamma(ramp->red,   gamma.red);
@@ -340,7 +397,7 @@ BOOL X11DRV_XF86VM_SetGammaRamp(LPDDGAMMARAMP ramp)
   {
       Bool ret;
       wine_tsx11_lock();
-      ret = XF86VidModeSetGammaRamp(gdi_display, DefaultScreen(gdi_display), 256,
+      ret = pXF86VidModeSetGammaRamp(gdi_display, DefaultScreen(gdi_display), 256,
 				    ramp->red, ramp->green, ramp->blue);
       wine_tsx11_unlock();
       return ret;
@@ -353,7 +410,7 @@ BOOL X11DRV_XF86VM_SetGammaRamp(LPDDGAMMARAMP ramp)
 	  ComputeGammaFromRamp(ramp->blue,  &gamma.blue)) {
 	  Bool ret;
 	  wine_tsx11_lock();
-	  ret = XF86VidModeSetGamma(gdi_display, DefaultScreen(gdi_display), &gamma);
+	  ret = pXF86VidModeSetGamma(gdi_display, DefaultScreen(gdi_display), &gamma);
 	  wine_tsx11_unlock();
 	  return ret;
       }
@@ -362,7 +419,7 @@ BOOL X11DRV_XF86VM_SetGammaRamp(LPDDGAMMARAMP ramp)
   return FALSE;
 }
 
-#endif /* HAVE_LIBXXF86VM */
+#endif /* SONAME_LIBXXF86VM */
 
 /***********************************************************************
  *		GetDeviceGammaRamp (X11DRV.@)
diff --git a/include/config.h.in b/include/config.h.in
index 9833b23..3ddc1a1 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -1083,6 +1083,9 @@
 /* Define to the soname of the libXrender library. */
 #undef SONAME_LIBXRENDER
 
+/* Define to the soname of the libXxf86vm library. */
+#undef SONAME_LIBXXF86VM
+
 /* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
 #undef STAT_MACROS_BROKEN
 
-- 
1.5.5.3




More information about the wine-patches mailing list