2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: lib/opengl32/icdload.c
5 * PURPOSE: OpenGL32 lib, ICD dll loader
12 WINE_DEFAULT_DEBUG_CHANNEL(opengl32
);
14 struct Drv_Opengl_Info
16 DWORD Version
; /*!< Driver interface version */
17 DWORD DriverVersion
; /*!< Driver version */
18 WCHAR DriverName
[256]; /*!< Driver name */
21 static CRITICAL_SECTION icdload_cs
= {NULL
, -1, 0, 0, 0, 0};
22 static struct ICD_Data
* ICD_Data_List
= NULL
;
23 static const WCHAR OpenGLDrivers_Key
[] = L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\OpenGLDrivers";
25 static void APIENTRY
wglSetCurrentValue(PVOID value
)
27 IntSetCurrentICDPrivate(value
);
30 static PVOID APIENTRY
wglGetCurrentValue()
32 return IntGetCurrentICDPrivate();
35 static DHGLRC
wglGetDHGLRC(struct wgl_context
* context
)
37 return context
->dhglrc
;
40 /* GDI entry points (win32k) */
41 extern INT APIENTRY
GdiDescribePixelFormat(HDC hdc
, INT ipfd
, UINT cjpfd
, PPIXELFORMATDESCRIPTOR ppfd
);
42 extern BOOL APIENTRY
GdiSetPixelFormat(HDC hdc
, INT ipfd
);
43 extern BOOL APIENTRY
GdiSwapBuffers(HDC hdc
);
45 /* Retrieves the ICD data (driver version + relevant DLL entry points) for a device context */
46 struct ICD_Data
* IntGetIcdData(HDC hdc
)
49 DWORD dwInput
, dwValueType
, Version
, DriverVersion
, Flags
;
50 struct Drv_Opengl_Info DrvInfo
;
51 struct ICD_Data
* data
;
53 WCHAR DllName
[MAX_PATH
];
54 BOOL (WINAPI
*DrvValidateVersion
)(DWORD
);
55 void (WINAPI
*DrvSetCallbackProcs
)(int nProcs
, PROC
* pProcs
);
57 /* First, see if the driver supports this */
58 dwInput
= OPENGL_GETINFO
;
68 /* Driver doesn't support opengl */
72 /* Query for the ICD DLL name and version */
83 ERR("Driver claims to support OPENGL_GETINFO escape code, but doesn't.\n");
87 /* Protect the list while we are loading*/
88 EnterCriticalSection(&icdload_cs
);
90 /* Search for it in the list of already loaded modules */
94 if(!_wcsicmp(data
->DriverName
, DrvInfo
.DriverName
))
97 TRACE("Found already loaded %p.\n", data
);
98 LeaveCriticalSection(&icdload_cs
);
104 /* It was still not loaded, look for it in the registry */
105 ret
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, OpenGLDrivers_Key
, 0, KEY_READ
, &OglKey
);
106 if(ret
!= ERROR_SUCCESS
)
108 ERR("Failed to open the OpenGLDrivers key.\n");
111 ret
= RegOpenKeyExW(OglKey
, DrvInfo
.DriverName
, 0, KEY_READ
, &DrvKey
);
112 if(ret
!= ERROR_SUCCESS
)
114 /* Some driver installer just provide the DLL name, like the Matrox G400 */
115 TRACE("No driver subkey for %S, trying to get DLL name directly.\n", DrvInfo
.DriverName
);
116 dwInput
= sizeof(DllName
);
117 ret
= RegQueryValueExW(OglKey
, DrvInfo
.DriverName
, 0, &dwValueType
, (LPBYTE
)DllName
, &dwInput
);
118 if((ret
!= ERROR_SUCCESS
) || (dwValueType
!= REG_SZ
))
120 ERR("Unable to get ICD DLL name!.\n");
124 Version
= DriverVersion
= Flags
= 0;
125 TRACE("DLL name is %S.\n", DllName
);
129 /* The driver have a subkey for the ICD */
130 TRACE("Querying details from registry for %S.\n", DrvInfo
.DriverName
);
131 dwInput
= sizeof(DllName
);
132 ret
= RegQueryValueExW(DrvKey
, L
"Dll", 0, &dwValueType
, (LPBYTE
)DllName
, &dwInput
);
133 if((ret
!= ERROR_SUCCESS
) || (dwValueType
!= REG_SZ
))
135 ERR("Unable to get ICD DLL name!.\n");
141 dwInput
= sizeof(Version
);
142 ret
= RegQueryValueExW(DrvKey
, L
"Version", 0, &dwValueType
, (LPBYTE
)&Version
, &dwInput
);
143 if((ret
!= ERROR_SUCCESS
) || (dwValueType
!= REG_DWORD
))
145 WARN("No version in driver subkey\n");
147 else if(Version
!= DrvInfo
.Version
)
149 ERR("Version mismatch between registry (%lu) and display driver (%lu).\n", Version
, DrvInfo
.Version
);
155 dwInput
= sizeof(DriverVersion
);
156 ret
= RegQueryValueExW(DrvKey
, L
"DriverVersion", 0, &dwValueType
, (LPBYTE
)&DriverVersion
, &dwInput
);
157 if((ret
!= ERROR_SUCCESS
) || (dwValueType
!= REG_DWORD
))
159 WARN("No driver version in driver subkey\n");
161 else if(DriverVersion
!= DrvInfo
.DriverVersion
)
163 ERR("Driver version mismatch between registry (%lu) and display driver (%lu).\n", DriverVersion
, DrvInfo
.DriverVersion
);
169 dwInput
= sizeof(Flags
);
170 ret
= RegQueryValueExW(DrvKey
, L
"Flags", 0, &dwValueType
, (LPBYTE
)&Flags
, &dwInput
);
171 if((ret
!= ERROR_SUCCESS
) || (dwValueType
!= REG_DWORD
))
173 WARN("No driver version in driver subkey\n");
179 TRACE("DLL name is %S, Version %lx, DriverVersion %lx, Flags %lx.\n", DllName
, Version
, DriverVersion
, Flags
);
181 /* No need for this anymore */
184 /* So far so good, allocate data */
185 data
= HeapAlloc(GetProcessHeap(), 0, sizeof(*data
));
188 ERR("Unable to allocate ICD data!\n");
192 /* Load the library */
193 data
->hModule
= LoadLibraryW(DllName
);
196 ERR("Could not load the ICD DLL: %S.\n", DllName
);
197 HeapFree(GetProcessHeap(), 0, data
);
203 * Validate version, if needed.
204 * Some drivers (at least VBOX), initialize stuff upon this call.
206 DrvValidateVersion
= (void*)GetProcAddress(data
->hModule
, "DrvValidateVersion");
207 if(DrvValidateVersion
)
209 if(!DrvValidateVersion(DrvInfo
.DriverVersion
))
211 ERR("DrvValidateVersion failed!.\n");
216 /* Pass the callbacks */
217 DrvSetCallbackProcs
= (void*)GetProcAddress(data
->hModule
, "DrvSetCallbackProcs");
218 if(DrvSetCallbackProcs
)
220 PROC callbacks
[] = {(PROC
)wglGetCurrentValue
,
221 (PROC
)wglSetCurrentValue
,
223 DrvSetCallbackProcs(3, callbacks
);
226 /* Get the DLL exports */
227 #define DRV_LOAD(x) do \
229 data->x = (void*)GetProcAddress(data->hModule, #x); \
231 ERR("%S lacks " #x "!\n", DllName); \
235 DRV_LOAD(DrvCopyContext
);
236 DRV_LOAD(DrvCreateContext
);
237 DRV_LOAD(DrvCreateLayerContext
);
238 DRV_LOAD(DrvDeleteContext
);
239 DRV_LOAD(DrvDescribeLayerPlane
);
240 DRV_LOAD(DrvDescribePixelFormat
);
241 DRV_LOAD(DrvGetLayerPaletteEntries
);
242 DRV_LOAD(DrvGetProcAddress
);
243 DRV_LOAD(DrvReleaseContext
);
244 DRV_LOAD(DrvRealizeLayerPalette
);
245 DRV_LOAD(DrvSetContext
);
246 DRV_LOAD(DrvSetLayerPaletteEntries
);
247 DRV_LOAD(DrvSetPixelFormat
);
248 DRV_LOAD(DrvShareLists
);
249 DRV_LOAD(DrvSwapBuffers
);
250 DRV_LOAD(DrvSwapLayerBuffers
);
253 /* Let's see if GDI should handle this instead of the ICD DLL */
254 // FIXME: maybe there is a better way
255 if (GdiDescribePixelFormat(hdc
, 0, 0, NULL
) != 0)
257 /* GDI knows what to do with that. Override */
258 TRACE("Forwarding WGL calls to win32k!\n");
259 data
->DrvDescribePixelFormat
= GdiDescribePixelFormat
;
260 data
->DrvSetPixelFormat
= GdiSetPixelFormat
;
261 data
->DrvSwapBuffers
= GdiSwapBuffers
;
264 /* Copy the DriverName */
265 wcscpy(data
->DriverName
, DrvInfo
.DriverName
);
268 data
->next
= ICD_Data_List
;
269 ICD_Data_List
= data
;
271 TRACE("Returning %p.\n", data
);
274 /* Unlock and return */
275 LeaveCriticalSection(&icdload_cs
);
279 LeaveCriticalSection(&icdload_cs
);
280 FreeLibrary(data
->hModule
);
281 HeapFree(GetProcessHeap(), 0, data
);
285 void IntDeleteAllICDs(void)
287 struct ICD_Data
* data
;
289 EnterCriticalSection(&icdload_cs
);
291 while (ICD_Data_List
!= NULL
)
293 data
= ICD_Data_List
;
294 ICD_Data_List
= data
->next
;
296 FreeLibrary(data
->hModule
);
297 HeapFree(GetProcessHeap(), 0, data
);