From 6dad1e8377cd8be7deaa373bf25bcd053684fdf0 Mon Sep 17 00:00:00 2001
From: Erich Hoover <ehoover@mines.edu>
Date: Sun, 14 Jun 2009 12:39:00 -0600
Subject: Add "manufacturer" driver on top of OS driver (winex11.drv).

---
 configure.ac                      |   12 ++++
 dlls/Makefile.in                  |    5 ++
 dlls/atiumdag/Makefile.in         |   23 +++++++
 dlls/atiumdag/atiumdag.c          |   55 ++++++++++++++++
 dlls/atiumdag/version.rc          |   22 +++++++
 dlls/gdi32/driver.c               |  126 ++++++++++++++++++++++++++++++++-----
 dlls/gdi32/gdi32.spec             |    2 +
 dlls/gdi32/gdi_private.h          |    1 +
 dlls/igdumd32/Makefile.in         |   23 +++++++
 dlls/igdumd32/igdumd32.c          |   55 ++++++++++++++++
 dlls/igdumd32/version.rc          |   22 +++++++
 dlls/imm32/imm.c                  |   31 +++-------
 dlls/nv4_disp/Makefile.in         |   23 +++++++
 dlls/nv4_disp/nv4_disp.c          |   55 ++++++++++++++++
 dlls/nv4_disp/version.rc          |   22 +++++++
 dlls/opengl32/wgl.c               |   20 +++++-
 dlls/user32/driver.c              |   27 ++-------
 dlls/wined3d/directx.c            |   15 +++++
 dlls/wined3d/wined3d_main.c       |    6 ++-
 dlls/winex11.drv/Makefile.in      |    1 +
 dlls/winex11.drv/opengl.c         |   14 ++++
 dlls/winex11.drv/winex11.drv.spec |    1 +
 dlls/wintab32/Makefile.in         |    2 +-
 dlls/wintab32/wintab32.c          |    6 ++-
 tools/make_video_spec             |   32 +++++++++
 25 files changed, 535 insertions(+), 66 deletions(-)
 create mode 100644 dlls/atiumdag/Makefile.in
 create mode 100644 dlls/atiumdag/atiumdag.c
 create mode 100644 dlls/atiumdag/version.rc
 create mode 100644 dlls/igdumd32/Makefile.in
 create mode 100644 dlls/igdumd32/igdumd32.c
 create mode 100644 dlls/igdumd32/version.rc
 create mode 100644 dlls/nv4_disp/Makefile.in
 create mode 100644 dlls/nv4_disp/nv4_disp.c
 create mode 100644 dlls/nv4_disp/version.rc
 create mode 100755 tools/make_video_spec

diff --git a/configure.ac b/configure.ac
index 99a60bc..6a4ce14 100644
--- a/configure.ac
+++ b/configure.ac
@@ -18,6 +18,15 @@ AC_ARG_ENABLE(win64, AS_HELP_STRING([--enable-win64],[build a Win64 emulator on
 AC_ARG_ENABLE(tests, AS_HELP_STRING([--disable-tests],[do not build the regression tests]))
 AC_ARG_ENABLE(maintainer-mode, AS_HELP_STRING([--enable-maintainer-mode],[enable maintainer-specific build rules]),
                                ,[AC_SUBST([MAINTAINER_MODE],[\#])])
+AC_ARG_ENABLE(video-driver,
+        AS_HELP_STRING([--enable-video-driver=<driver>],[use <driver> for video (x11,quartz,etc.)])
+    ,
+        AC_SUBST(WINE_VIDEO_DRIVER,$enableval)
+        AC_DEFINE(WINE_VIDEO_DRIVER,"$enableval",[OS video driver])
+    ,
+        AC_SUBST(WINE_VIDEO_DRIVER,x11)
+        AC_DEFINE(WINE_VIDEO_DRIVER,"x11",[OS video driver])
+)
 
 AC_ARG_WITH(alsa,      AS_HELP_STRING([--without-alsa],[do not use the Alsa sound support]),
             [if test "x$withval" = "xno"; then ac_cv_header_sys_asoundlib_h=no; ac_cv_header_alsa_asoundlib_h=no; fi])
@@ -1914,6 +1923,7 @@ WINE_CONFIG_MAKEFILE([dlls/advpack/tests/Makefile],[dlls/Maketest.rules],[dlls],
 WINE_CONFIG_MAKEFILE([dlls/amstream/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
 WINE_CONFIG_MAKEFILE([dlls/amstream/tests/Makefile],[dlls/Maketest.rules],[dlls],[ALL_TEST_DIRS],[enable_tests])
 WINE_CONFIG_MAKEFILE([dlls/appwiz.cpl/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
+WINE_CONFIG_MAKEFILE([dlls/atiumdag/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
 WINE_CONFIG_MAKEFILE([dlls/atl/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
 WINE_CONFIG_MAKEFILE([dlls/authz/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
 WINE_CONFIG_MAKEFILE([dlls/avicap32/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
@@ -2049,6 +2059,7 @@ WINE_CONFIG_MAKEFILE([dlls/httpapi/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DL
 WINE_CONFIG_MAKEFILE([dlls/iccvid/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
 WINE_CONFIG_MAKEFILE([dlls/icmp/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
 WINE_CONFIG_MAKEFILE([dlls/ifsmgr.vxd/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS],[enable_win16])
+WINE_CONFIG_MAKEFILE([dlls/igdumd32/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
 WINE_CONFIG_MAKEFILE([dlls/imaadp32.acm/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
 WINE_CONFIG_MAKEFILE([dlls/imagehlp/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
 WINE_CONFIG_MAKEFILE([dlls/imm.dll16/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS],[enable_win16])
@@ -2152,6 +2163,7 @@ WINE_CONFIG_MAKEFILE([dlls/ntdsapi/tests/Makefile],[dlls/Maketest.rules],[dlls],
 WINE_CONFIG_MAKEFILE([dlls/ntoskrnl.exe/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
 WINE_CONFIG_MAKEFILE([dlls/ntprint/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
 WINE_CONFIG_MAKEFILE([dlls/ntprint/tests/Makefile],[dlls/Maketest.rules],[dlls],[ALL_TEST_DIRS],[enable_tests])
+WINE_CONFIG_MAKEFILE([dlls/nv4_disp/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
 WINE_CONFIG_MAKEFILE([dlls/objsel/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
 WINE_CONFIG_MAKEFILE([dlls/odbc32/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
 WINE_CONFIG_MAKEFILE([dlls/odbccp32/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
diff --git a/dlls/Makefile.in b/dlls/Makefile.in
index b600c3a..62d0c64 100644
--- a/dlls/Makefile.in
+++ b/dlls/Makefile.in
@@ -213,6 +213,7 @@ IMPORT_LIBS = \
 	vdmdbg/libvdmdbg.$(IMPLIBEXT) \
 	version/libversion.$(IMPLIBEXT) \
 	wined3d/libwined3d.$(IMPLIBEXT) \
+	winex11.drv/libwinex11.drv.$(IMPLIBEXT) \
 	winhttp/libwinhttp.$(IMPLIBEXT) \
 	wininet/libwininet.$(IMPLIBEXT) \
 	winmm/libwinmm.$(IMPLIBEXT) \
@@ -356,6 +357,7 @@ CROSS_IMPLIBS = \
 	vdmdbg/libvdmdbg.a \
 	version/libversion.a \
 	wined3d/libwined3d.a \
+	winex11.drv/libwinex11.drv.a \
 	winhttp/libwinhttp.a \
 	wininet/libwininet.a \
 	winmm/libwinmm.a \
@@ -755,6 +757,9 @@ version/libversion.def version/libversion.a: version/version.spec $(WINEBUILD)
 wined3d/libwined3d.def wined3d/libwined3d.a: wined3d/wined3d.spec $(WINEBUILD)
 	@cd wined3d && $(MAKE) `basename $@`
 
+winex11.drv/libwinex11.drv.def winex11.drv/libwinex11.drv.a: winex11.drv/winex11.drv.spec $(WINEBUILD)
+	@cd winex11.drv && $(MAKE) `basename $@`
+
 winhttp/libwinhttp.def winhttp/libwinhttp.a: winhttp/winhttp.spec $(WINEBUILD)
 	@cd winhttp && $(MAKE) `basename $@`
 
diff --git a/dlls/atiumdag/Makefile.in b/dlls/atiumdag/Makefile.in
new file mode 100644
index 0000000..7b4e374
--- /dev/null
+++ b/dlls/atiumdag/Makefile.in
@@ -0,0 +1,23 @@
+VIDEODRIVER  = wine@WINE_VIDEO_DRIVER@.drv
+
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+MODULE    = atiumdag.dll
+IMPORTS   = wine@WINE_VIDEO_DRIVER@.drv
+EXTRAINCL =
+EXTRALIBS =
+
+C_SRCS = \
+	atiumdag.c
+
+RC_SRCS = version.rc
+
+@MAKE_DLL_RULES@
+
+atiumdag.spec: ../$(VIDEODRIVER)/$(VIDEODRIVER).spec
+	$(TOOLSDIR)/tools/make_video_spec $(VIDEODRIVER) atiumdag.spec
+
+@DEPENDENCIES@  # everything below this line is overwritten by make depend
+
diff --git a/dlls/atiumdag/atiumdag.c b/dlls/atiumdag/atiumdag.c
new file mode 100644
index 0000000..8ae4e83
--- /dev/null
+++ b/dlls/atiumdag/atiumdag.c
@@ -0,0 +1,55 @@
+/*
+ * Wine ATI Video Passthrough Driver
+ *
+ * Copyright 1998 Patrik Stridvall
+ * Copyright 2000 Alexandre Julliard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+
+#include "wine/server.h"
+#include "wine/debug.h"
+#include "wine/library.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(video);
+
+/***********************************************************************
+ *           Driver initialisation routine
+ */
+BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
+{
+    /* Attach/Detach are performed in the actual video driver */
+    return TRUE;
+}
+
diff --git a/dlls/atiumdag/version.rc b/dlls/atiumdag/version.rc
new file mode 100644
index 0000000..a89f9e8
--- /dev/null
+++ b/dlls/atiumdag/version.rc
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2007 Alexandre Julliard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define WINE_FILEDESCRIPTION_STR "Wine ATI Video Passthrough Driver"
+#define WINE_FILENAME_STR "atiumdag.dll"
+
+#include "wine/wine_common_ver.rc"
diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c
index 20d3f36..bf02893 100644
--- a/dlls/gdi32/driver.c
+++ b/dlls/gdi32/driver.c
@@ -33,6 +33,21 @@
 #include "wine/unicode.h"
 #include "wine/debug.h"
 
+#ifdef HAVE_GL_GL_H
+# include <GL/gl.h>
+
+typedef struct driver_entry {
+    const char *filename;
+    const char *vendor_name;
+} DriverEntry;
+
+DriverEntry native_drivers[] = {
+    {"nv4_disp.dll", "NVIDIA"},
+    {"atiumdag.dll", "ATI"},
+    {"igdumd32.dll", "Intel(R)"}
+};
+#endif
+
 WINE_DEFAULT_DEBUG_CHANNEL(driver);
 
 struct graphics_driver
@@ -207,6 +222,7 @@ static struct graphics_driver *create_driver( HMODULE module )
         GET_FUNC(wglShareLists);
         GET_FUNC(wglUseFontBitmapsA);
         GET_FUNC(wglUseFontBitmapsW);
+        GET_FUNC(wine_glGetVendor);
 #undef GET_FUNC
     }
     else memset( &driver->funcs, 0, sizeof(driver->funcs) );
@@ -220,31 +236,86 @@ static struct graphics_driver *create_driver( HMODULE module )
 
 
 /**********************************************************************
- *	     load_display_driver
+ *	     __wine_get_video_driver
  *
- * Special case for loading the display driver: get the name from the config file
+ * Mechanism for returning the module handle for the video driver.
+ * Return must be freed with FreeLibrary().
  */
-static struct graphics_driver *load_display_driver(void)
+HMODULE CDECL __wine_get_video_driver(const char *registry_key, char *driver_name_ret,
+                                      BOOL force_os_driver)
 {
     char buffer[MAX_PATH], libname[32], *name, *next;
-    HMODULE module = 0;
+    BOOL report_native_video_driver = FALSE;
+    HMODULE module = NULL;
     HKEY hkey;
 
-    if (display_driver)  /* already loaded */
-    {
-        display_driver->count++;
-        return display_driver;
-    }
-
-    strcpy( buffer, "x11" );  /* default value */
     /* @@ Wine registry key: HKCU\Software\Wine\Drivers */
+    strcpy( buffer, WINE_VIDEO_DRIVER );  /* default value */
     if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Drivers", &hkey ))
     {
-        DWORD type, count = sizeof(buffer);
-        RegQueryValueExA( hkey, "Graphics", 0, &type, (LPBYTE) buffer, &count );
+        char yn_buffer[10];
+        DWORD type, count;
+
+        count = sizeof(yn_buffer);
+        RegQueryValueExA( hkey, "ReportNativeVideoDriver", 0, &type, (LPBYTE) yn_buffer, &count );
+        if(!strcasecmp(yn_buffer, "Y"))
+            report_native_video_driver = TRUE;
+        count = sizeof(buffer);
+        RegQueryValueExA( hkey, registry_key, 0, &type, (LPBYTE) buffer, &count );
         RegCloseKey( hkey );
     }
 
+    /* Attempt to report a native driver */
+    if(report_native_video_driver && !force_os_driver)
+    {
+#ifdef HAVE_GL_GL_H
+        static struct graphics_driver *parent_display_driver = NULL;
+        const char *driver_filename = NULL;
+        const char *gl_vendor = NULL;
+        HMODULE parent_module = NULL;
+        int i;
+
+        /* Load OpenGL and obtain the pointer to glGetString */
+        if(parent_display_driver == NULL)
+        {
+            parent_module = __wine_get_video_driver("Graphics", NULL, TRUE);
+            if (!(parent_display_driver = create_driver( parent_module )))
+            {
+                MESSAGE( "Could not create parent graphics driver!\n" );
+                goto failed;
+            }
+        }
+        /* Use the vendor name to report a native driver
+         * Note: this will fail until libGL is initialized.
+         */
+        gl_vendor = (const char *) parent_display_driver->funcs.pwine_glGetVendor();
+        if (gl_vendor == NULL)
+            goto failed;
+        for (i=0;i<sizeof(native_drivers)/sizeof(DriverEntry);i++)
+        {
+            if (strstr(gl_vendor, native_drivers[i].vendor_name))
+            {
+                driver_filename = native_drivers[i].filename;
+                break;
+            }
+        }
+
+failed:
+        if (parent_module != NULL)
+            FreeLibrary( parent_module );
+        /* Load the discovered native driver */
+        if (driver_filename != NULL)
+        {
+            snprintf( libname, sizeof(libname), driver_filename );
+            if ((module = LoadLibraryA( libname )) != NULL)
+                goto complete;
+        }
+#else
+        FIXME("ReportNativeVideoDriver requires OpenGL.\n");
+#endif
+    }
+
+    /* Either no known native driver was available or native reporting was not desired */
     name = buffer;
     while (name)
     {
@@ -252,13 +323,38 @@ static struct graphics_driver *load_display_driver(void)
         if (next) *next++ = 0;
 
         snprintf( libname, sizeof(libname), "wine%s.drv", name );
-        if ((module = LoadLibraryA( libname )) != 0) break;
+        if ((module = LoadLibraryA( libname )) != NULL) break;
         name = next;
     }
 
+complete:
+    TRACE("Loaded graphics driver '%s'.\n", libname);
+    if(driver_name_ret)
+        strcpy(driver_name_ret, libname);
+    return module;
+}
+
+
+/**********************************************************************
+ *	     load_display_driver
+ *
+ * Special case for loading the display driver: get the name from the config file
+ */
+static struct graphics_driver *load_display_driver(void)
+{
+    char driver_name[32];
+    HMODULE module = 0;
+
+    if (display_driver)  /* already loaded */
+    {
+        display_driver->count++;
+        return display_driver;
+    }
+
+    module = __wine_get_video_driver("Graphics", (char *) driver_name, FALSE);
     if (!(display_driver = create_driver( module )))
     {
-        MESSAGE( "Could not create graphics driver '%s'\n", buffer );
+        MESSAGE( "Could not create graphics driver '%s'\n", driver_name );
         FreeLibrary( module );
         ExitProcess(1);
     }
diff --git a/dlls/gdi32/gdi32.spec b/dlls/gdi32/gdi32.spec
index 36a8fb1..e5bf79d 100644
--- a/dlls/gdi32/gdi32.spec
+++ b/dlls/gdi32/gdi32.spec
@@ -528,5 +528,7 @@
 # All functions must be prefixed with '__wine_' (for internal functions)
 # or 'wine_' (for user-visible functions) to avoid namespace conflicts.
 
+# Get video driver handle
+@ cdecl __wine_get_video_driver(str ptr)
 # GDI objects
 @ cdecl __wine_make_gdi_object_system(long long)
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index da66ade..768419b 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -209,6 +209,7 @@ typedef struct tagDC_FUNCS
     BOOL     (CDECL *pwglShareLists)(HGLRC hglrc1, HGLRC hglrc2);
     BOOL     (CDECL *pwglUseFontBitmapsA)(PHYSDEV, DWORD, DWORD, DWORD);
     BOOL     (CDECL *pwglUseFontBitmapsW)(PHYSDEV, DWORD, DWORD, DWORD);
+    const char *(CDECL *pwine_glGetVendor)();
 } DC_FUNCTIONS;
 
 /* It should not be necessary to access the contents of the GdiPath
diff --git a/dlls/igdumd32/Makefile.in b/dlls/igdumd32/Makefile.in
new file mode 100644
index 0000000..24e7b7c
--- /dev/null
+++ b/dlls/igdumd32/Makefile.in
@@ -0,0 +1,23 @@
+VIDEODRIVER  = wine@WINE_VIDEO_DRIVER@.drv
+
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+MODULE    = igdumd32.dll
+IMPORTS   = wine@WINE_VIDEO_DRIVER@.drv
+EXTRAINCL =
+EXTRALIBS =
+
+C_SRCS = \
+	igdumd32.c
+
+RC_SRCS = version.rc
+
+@MAKE_DLL_RULES@
+
+igdumd32.spec: ../$(VIDEODRIVER)/$(VIDEODRIVER).spec
+	$(TOOLSDIR)/tools/make_video_spec $(VIDEODRIVER) igdumd32.spec
+
+@DEPENDENCIES@  # everything below this line is overwritten by make depend
+
diff --git a/dlls/igdumd32/igdumd32.c b/dlls/igdumd32/igdumd32.c
new file mode 100644
index 0000000..ede47f0
--- /dev/null
+++ b/dlls/igdumd32/igdumd32.c
@@ -0,0 +1,55 @@
+/*
+ * Wine Intel Video Passthrough Driver
+ *
+ * Copyright 1998 Patrik Stridvall
+ * Copyright 2000 Alexandre Julliard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+
+#include "wine/server.h"
+#include "wine/debug.h"
+#include "wine/library.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(video);
+
+/***********************************************************************
+ *           Driver initialisation routine
+ */
+BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
+{
+    /* Attach/Detach are performed in the actual video driver */
+    return TRUE;
+}
+
diff --git a/dlls/igdumd32/version.rc b/dlls/igdumd32/version.rc
new file mode 100644
index 0000000..94bbb2f
--- /dev/null
+++ b/dlls/igdumd32/version.rc
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2007 Alexandre Julliard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define WINE_FILEDESCRIPTION_STR "Wine Intel Video Passthrough Driver"
+#define WINE_FILENAME_STR "igdumd32.dll"
+
+#include "wine/wine_common_ver.rc"
diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c
index cb97ecd..e86a5ca 100644
--- a/dlls/imm32/imm.c
+++ b/dlls/imm32/imm.c
@@ -243,34 +243,19 @@ static void IMM_FreeThreadData(void)
     }
 }
 
+/* gdi32 routine for retrieving the video driver */
+extern HMODULE CDECL __wine_get_video_driver(const char *registry_key, char *driver_name_ret,
+                                             BOOL force_os_driver);
+
 static HMODULE LoadDefaultWineIME(void)
 {
-    char buffer[MAX_PATH], libname[32], *name, *next;
-    HMODULE module = 0;
-    HKEY hkey;
+    HMODULE module = NULL;
 
     TRACE("Attempting to fall back to wine default IME\n");
 
-    strcpy( buffer, "x11" );  /* default value */
-    /* @@ Wine registry key: HKCU\Software\Wine\Drivers */
-    if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Drivers", &hkey ))
-    {
-        DWORD type, count = sizeof(buffer);
-        RegQueryValueExA( hkey, "Ime", 0, &type, (LPBYTE) buffer, &count );
-        RegCloseKey( hkey );
-    }
-
-    name = buffer;
-    while (name)
-    {
-        next = strchr( name, ',' );
-        if (next) *next++ = 0;
-
-        snprintf( libname, sizeof(libname), "wine%s.drv", name );
-        if ((module = LoadLibraryA( libname )) != 0) break;
-        name = next;
-    }
-
+    module = __wine_get_video_driver("Ime", NULL, FALSE);
+    if(module == NULL)
+        FIXME("Failed to load IME driver.\n");
     return module;
 }
 
diff --git a/dlls/nv4_disp/Makefile.in b/dlls/nv4_disp/Makefile.in
new file mode 100644
index 0000000..43c91c3
--- /dev/null
+++ b/dlls/nv4_disp/Makefile.in
@@ -0,0 +1,23 @@
+VIDEODRIVER  = wine@WINE_VIDEO_DRIVER@.drv
+
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+MODULE    = nv4_disp.dll
+IMPORTS   = wine@WINE_VIDEO_DRIVER@.drv
+EXTRAINCL =
+EXTRALIBS =
+
+C_SRCS = \
+	nv4_disp.c
+
+RC_SRCS = version.rc
+
+@MAKE_DLL_RULES@
+
+nv4_disp.spec: ../$(VIDEODRIVER)/$(VIDEODRIVER).spec
+	$(TOOLSDIR)/tools/make_video_spec $(VIDEODRIVER) nv4_disp.spec
+
+@DEPENDENCIES@  # everything below this line is overwritten by make depend
+
diff --git a/dlls/nv4_disp/nv4_disp.c b/dlls/nv4_disp/nv4_disp.c
new file mode 100644
index 0000000..a5ec647
--- /dev/null
+++ b/dlls/nv4_disp/nv4_disp.c
@@ -0,0 +1,55 @@
+/*
+ * Wine nVidia Video Passthrough Driver
+ *
+ * Copyright 1998 Patrik Stridvall
+ * Copyright 2000 Alexandre Julliard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+
+#include "wine/server.h"
+#include "wine/debug.h"
+#include "wine/library.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(video);
+
+/***********************************************************************
+ *           Driver initialisation routine
+ */
+BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
+{
+    /* Attach/Detach are performed in the actual video driver */
+    return TRUE;
+}
+
diff --git a/dlls/nv4_disp/version.rc b/dlls/nv4_disp/version.rc
new file mode 100644
index 0000000..45882e7
--- /dev/null
+++ b/dlls/nv4_disp/version.rc
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2007 Alexandre Julliard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define WINE_FILEDESCRIPTION_STR "Wine nVidia Video Passthrough Driver"
+#define WINE_FILENAME_STR "nv4_disp.dll"
+
+#include "wine/wine_common_ver.rc"
diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c
index 34f7f07..0cbf318 100644
--- a/dlls/opengl32/wgl.c
+++ b/dlls/opengl32/wgl.c
@@ -691,21 +691,35 @@ void WINAPI wine_glGetIntegerv( GLenum pname, GLint* params )
 }
 
 
+/* gdi32 routine for retrieving the video driver */
+typedef HMODULE CDECL (video_driver_fn)(const char *registry_key, char *driver_name_ret,
+                                        BOOL force_os_driver);
+
+video_driver_fn *__wine_get_video_driver;
+
 /* This is for brain-dead applications that use OpenGL functions before even
    creating a rendering context.... */
 static BOOL process_attach(void)
 {
   HMODULE mod_x11, mod_gdi32;
+  char video_driver[32];
   DWORD size;
   HKEY hkey = 0;
 
   GetDesktopWindow();  /* make sure winex11 is loaded (FIXME) */
-  mod_x11 = GetModuleHandleA( "winex11.drv" );
   mod_gdi32 = GetModuleHandleA( "gdi32.dll" );
 
-  if (!mod_x11 || !mod_gdi32)
+  if (!mod_gdi32)
+  {
+      ERR("GDI32 not loaded. Cannot create default context.\n");
+      return FALSE;
+  }
+  __wine_get_video_driver = (video_driver_fn *) GetProcAddress( mod_gdi32, "__wine_get_video_driver" );
+  mod_x11 = __wine_get_video_driver( "Graphics", (char *) video_driver, FALSE );
+  if (!mod_x11)
   {
-      ERR("X11DRV or GDI32 not loaded. Cannot create default context.\n");
+      ERR("Video driver (%s) not loaded. Cannot create default context.\n", video_driver);
+      FreeLibrary(mod_gdi32);
       return FALSE;
   }
 
diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c
index 6454f65..0720647 100644
--- a/dlls/user32/driver.c
+++ b/dlls/user32/driver.c
@@ -32,35 +32,18 @@ static USER_DRIVER null_driver, lazy_load_driver;
 const USER_DRIVER *USER_Driver = &lazy_load_driver;
 static DWORD driver_load_error;
 
+/* gdi32 routine for retrieving the video driver */
+extern HMODULE CDECL __wine_get_video_driver(const char *registry_key, char *driver_name_ret,
+                                             BOOL force_os_driver);
+
 /* load the graphics driver */
 static const USER_DRIVER *load_driver(void)
 {
-    char buffer[MAX_PATH], libname[32], *name, *next;
-    HKEY hkey;
     void *ptr;
     HMODULE graphics_driver;
     USER_DRIVER *driver, *prev;
 
-    strcpy( buffer, "x11" );  /* default value */
-    /* @@ Wine registry key: HKCU\Software\Wine\Drivers */
-    if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Drivers", &hkey ))
-    {
-        DWORD type, count = sizeof(buffer);
-        RegQueryValueExA( hkey, "Graphics", 0, &type, (LPBYTE) buffer, &count );
-        RegCloseKey( hkey );
-    }
-
-    name = buffer;
-    while (name)
-    {
-        next = strchr( name, ',' );
-        if (next) *next++ = 0;
-
-        snprintf( libname, sizeof(libname), "wine%s.drv", name );
-        if ((graphics_driver = LoadLibraryA( libname )) != 0) break;
-        name = next;
-    }
-
+    graphics_driver = __wine_get_video_driver("Graphics", NULL, FALSE);
     if (!graphics_driver)
         driver_load_error = GetLastError();
 
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 05443fc..6727149 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -1734,6 +1734,7 @@ static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Ad
         strcpy(pIdentifier->Description, This->adapters[Adapter].gl_info.driver_description);
     else /* Copy default description "Direct3D HAL" */
         strcpy(pIdentifier->Description, This->adapters[Adapter].description);
+FIXME("EEH Driver name: %s\n", pIdentifier->Driver);
 
     /* Note dx8 doesn't supply a DeviceName */
     if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY1"); /* FIXME: May depend on desktop? */
@@ -4432,11 +4433,17 @@ static void fillGLAttribFuncs(const WineD3D_GL_Info *gl_info)
     }
 }
 
+/* gdi32 routine for retrieving the video driver */
+extern HMODULE CDECL __wine_get_video_driver(const char *registry_key, char *driver_name_ret,
+                                             BOOL force_os_driver);
+
 BOOL InitAdapters(IWineD3DImpl *This)
 {
     static HMODULE mod_gl;
     BOOL ret;
     int ps_selected_mode, vs_selected_mode;
+    HMODULE driver_handle = NULL;
+    static char driver_name[32];
 
     /* No need to hold any lock. The calling library makes sure only one thread calls
      * wined3d simultaneously
@@ -4532,6 +4539,9 @@ BOOL InitAdapters(IWineD3DImpl *This)
         adapter->driver = "Display";
         adapter->description = "Direct3D HAL";
 
+        driver_handle = __wine_get_video_driver("Graphics", (char *) driver_name, FALSE);
+        adapter->driver = driver_name;
+        FreeLibrary(driver_handle);
         /* Use the VideoRamSize registry setting when set */
         if(wined3d_settings.emulated_textureram)
             adapter->TextureRam = wined3d_settings.emulated_textureram;
@@ -4714,6 +4724,11 @@ nogl_adapter:
 
     This->adapters[0].driver = "Display";
     This->adapters[0].description = "WineD3D DirectDraw Emulation";
+
+    driver_handle = __wine_get_video_driver("Graphics", (char *) driver_name, FALSE);
+    This->adapters[0].driver = driver_name;
+    FreeLibrary(driver_handle);
+
     if(wined3d_settings.emulated_textureram) {
         This->adapters[0].TextureRam = wined3d_settings.emulated_textureram;
     } else {
diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c
index f996aec..fdc1dcd 100644
--- a/dlls/wined3d/wined3d_main.c
+++ b/dlls/wined3d/wined3d_main.c
@@ -95,6 +95,10 @@ static void CDECL wined3d_do_nothing(void)
 {
 }
 
+/* gdi32 routine for retrieving the video driver */
+extern HMODULE CDECL __wine_get_video_driver(const char *registry_key, char **driver_name_ret,
+                                             BOOL force_os_driver);
+
 static BOOL wined3d_init(HINSTANCE hInstDLL)
 {
     HMODULE mod;
@@ -127,7 +131,7 @@ static BOOL wined3d_init(HINSTANCE hInstDLL)
 
     DisableThreadLibraryCalls(hInstDLL);
 
-    mod = GetModuleHandleA( "winex11.drv" );
+    mod = __wine_get_video_driver("Graphics", NULL, FALSE);
     if (mod)
     {
         wine_tsx11_lock_ptr   = (void *)GetProcAddress( mod, "wine_tsx11_lock" );
diff --git a/dlls/winex11.drv/Makefile.in b/dlls/winex11.drv/Makefile.in
index 0bafb33..017bbf3 100644
--- a/dlls/winex11.drv/Makefile.in
+++ b/dlls/winex11.drv/Makefile.in
@@ -3,6 +3,7 @@ TOPOBJDIR = ../..
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = winex11.drv
+IMPORTLIB = winex11.drv
 IMPORTS   = user32 gdi32 advapi32 imm32 kernel32 ntdll
 DELAYIMPORTS = comctl32
 EXTRAINCL = @X_CFLAGS@
diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c
index f207a32..2d82a2a 100644
--- a/dlls/winex11.drv/opengl.c
+++ b/dlls/winex11.drv/opengl.c
@@ -2218,6 +2218,20 @@ static const char * WINAPI X11DRV_wglGetExtensionsStringARB(HDC hdc) {
 }
 
 /**
+ * X11DRV_wine_glGetVendor
+ *
+ * Return the graphics card vendor
+ */
+const char * CDECL X11DRV_wine_glGetVendor(void) {
+    const char *vendor = NULL;
+
+    if(has_opengl())
+        vendor = WineGLInfo.glxClientVendor;
+    TRACE("() returning \"%s\"\n", vendor);
+    return vendor;
+}
+
+/**
  * X11DRV_wglCreatePbufferARB
  *
  * WGL_ARB_pbuffer: wglCreatePbufferARB
diff --git a/dlls/winex11.drv/winex11.drv.spec b/dlls/winex11.drv/winex11.drv.spec
index fdd32b3..e29e66c 100644
--- a/dlls/winex11.drv/winex11.drv.spec
+++ b/dlls/winex11.drv/winex11.drv.spec
@@ -145,6 +145,7 @@
 @ cdecl wglShareLists(long long) X11DRV_wglShareLists
 @ cdecl wglUseFontBitmapsA(ptr long long long) X11DRV_wglUseFontBitmapsA
 @ cdecl wglUseFontBitmapsW(ptr long long long) X11DRV_wglUseFontBitmapsW
+@ cdecl wine_glGetVendor() X11DRV_wine_glGetVendor
 
 #IME Interface
 @ stdcall ImeInquire(ptr wstr wstr)
diff --git a/dlls/wintab32/Makefile.in b/dlls/wintab32/Makefile.in
index b150914..7cdef3a 100644
--- a/dlls/wintab32/Makefile.in
+++ b/dlls/wintab32/Makefile.in
@@ -4,7 +4,7 @@ SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = wintab32.dll
 IMPORTLIB = wintab32
-IMPORTS   = user32 kernel32
+IMPORTS   = user32 gdi32 kernel32
 
 C_SRCS = \
 	context.c \
diff --git a/dlls/wintab32/wintab32.c b/dlls/wintab32/wintab32.c
index b52b429..a5f04eb 100644
--- a/dlls/wintab32/wintab32.c
+++ b/dlls/wintab32/wintab32.c
@@ -63,6 +63,10 @@ static VOID TABLET_Unregister(void)
     UnregisterClassW(WC_TABLETCLASSNAME, NULL);
 }
 
+/* gdi32 routine for retrieving the video driver */
+extern HMODULE CDECL __wine_get_video_driver(const char *registry_key, char *driver_name_ret,
+                                             BOOL force_os_driver);
+
 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
 {
     static const WCHAR name[] = {'T','a','b','l','e','t',0};
@@ -76,7 +80,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
             DisableThreadLibraryCalls(hInstDLL);
             InitializeCriticalSection(&csTablet);
             csTablet.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": csTablet");
-            hx11drv = GetModuleHandleA("winex11.drv");
+            hx11drv = __wine_get_video_driver("Graphics", NULL, FALSE);
             if (hx11drv)
             {
                 pLoadTabletInfo = (void *)GetProcAddress(hx11drv, "LoadTabletInfo");
diff --git a/tools/make_video_spec b/tools/make_video_spec
new file mode 100755
index 0000000..46393d6
--- /dev/null
+++ b/tools/make_video_spec
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+# Generate a video driver that passes calls through to the OS driver
+
+DRIVER="$1";
+OUTPUT="$2";
+
+WINESPEC="../${DRIVER}/${DRIVER}.spec";
+
+echo "## This file is created programatically from:" > ${OUTPUT};
+echo "## ${WINESPEC}" >> ${OUTPUT};
+
+exec < ${WINESPEC};
+while read LINE; do
+	if [ "${#LINE}" -eq "0" ]; then
+		echo "" >> ${OUTPUT};
+	fi
+	if [ "${LINE:0:1}" = "#" ]; then
+		echo "${LINE}" >> ${OUTPUT};
+	fi
+	if [ "${LINE:0:1}" != "@" ]; then
+		continue;
+	fi
+	PARAMS=`echo "${LINE}" | sed 's/\([^ ]*\)\([ ]*\)\([^ ]*\)\([ ]*\)\([^ ]*\)/\5/'`;
+	if [ "${PARAMS:0:1}" = "-" ]; then
+		SEDPARAMS="s/\([^ ]*\)\([ ]*\)\([^ ]*\)\([ ]*\)\([^ ]*\)\([ ]*\)\([^\(]*\)\([^)]*\)\([^\n]*\)/\1\2\3\4\5\6\7\8\) ${DRIVER}.\7/";
+	else
+		SEDPARAMS="s/\([^ ]*\)\([ ]*\)\([^ ]*\)\([ ]*\)\([^\(]*\)\([^)]*\)\([^\n]*\)/\1\2\3\4\5\6\) ${DRIVER}.\5/";
+	fi
+	echo "${LINE}" | sed "${SEDPARAMS}" >> ${OUTPUT};
+done
+
-- 
1.5.4.3

