In an effort to come up with a (hopefully palatable) solution to a
couple of bugs I've put together the attached patch.  Only the first
of the two issues is currently handled, though the patch paves the way
for the second issue.

1) Bug #15839: (not this title) Wine does not report the manufacturer
driver (for example, "nv4_disp.dll" for nVidia users)
2) Wine does not always report the correct amount of video RAM (not
sure if there is a bug number for this)

The approach handles graphics requests like this:
"manufacturer" driver  -->   "OS" driver (normally winex11.drv)

Where the manufacturer driver (at present) forwards all requests to
the OS driver.  Later additions could provide driver-specific code for
returning information such as the correct amount of video RAM.  Also,
the manufacturer driver is skipped (reverting to the current behavior)
unless "HKEY_CURRENT_USER\Software\Wine\Drivers\ReportNativeVideoDriver"
is set to "Y".

Note: patch makes changes to configure.ac, so cover your bases:
autoheader && autoconf && ./configure && make depend && make

I'm particularly interested in comments related to how the driver is
selected (__wine_get_video_driver in gdi32), but all feedback is
welcome.

Erich Hoover
[email protected]
From 6dad1e8377cd8be7deaa373bf25bcd053684fdf0 Mon Sep 17 00:00:00 2001
From: Erich Hoover <[email protected]>
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  = w...@[email protected]
+
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+MODULE    = atiumdag.dll
+IMPORTS   = w...@[email protected]
+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  = w...@[email protected]
+
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+MODULE    = igdumd32.dll
+IMPORTS   = w...@[email protected]
+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  = w...@[email protected]
+
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+MODULE    = nv4_disp.dll
+IMPORTS   = w...@[email protected]
+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



Reply via email to