1 /* $Id: opengl32.c,v 1.6 2004/02/02 17:59:23 navaraf Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: lib/opengl32/opengl32.c
6 * PURPOSE: OpenGL32 lib
7 * PROGRAMMER: Anich Gregor (blight), Royce Mitchell III
12 #define WIN32_LEAN_AND_MEAN
20 #define EXPORT __declspec(dllexport)
21 #define NAKED __attribute__((naked))
23 /* function prototypes */
24 static BOOL
OPENGL32_LoadDrivers();
25 static void OPENGL32_AppendICD( GLDRIVERDATA
*icd
);
26 static void OPENGL32_RemoveICD( GLDRIVERDATA
*icd
);
27 static GLDRIVERDATA
*OPENGL32_LoadDriver ( LPCWSTR regKey
);
28 static DWORD
OPENGL32_InitializeDriver( GLDRIVERDATA
*icd
);
29 static BOOL
OPENGL32_UnloadDriver( GLDRIVERDATA
*icd
);
32 const char* OPENGL32_funcnames
[GLIDX_COUNT
]
33 __attribute__((section("shared"), shared
)) =
40 GLPROCESSDATA OPENGL32_processdata
;
43 static void OPENGL32_ThreadDetach()
45 GLTHREADDATA
*lpvData
;
47 /* FIXME - do we need to release some HDC or something? */
48 lpvData
= (GLTHREADDATA
*)TlsGetValue ( OPENGL32_tls
);
49 if ( lpvData
!= NULL
)
50 LocalFree((HLOCAL
) lpvData
);
54 BOOL WINAPI
DllMain(HINSTANCE hInstance
, DWORD Reason
, LPVOID Reserved
)
56 GLTHREADDATA
* lpData
= NULL
;
57 DBGPRINT( "DllMain called!\n" );
61 /* The DLL is loading due to process
62 * initialization or a call to LoadLibrary.
64 case DLL_PROCESS_ATTACH
:
65 OPENGL32_tls
= TlsAlloc();
66 if ( 0xFFFFFFFF == OPENGL32_tls
)
69 memset( &OPENGL32_processdata
, 0, sizeof (OPENGL32_processdata
) );
71 /* get list of ICDs from registry: */
72 OPENGL32_LoadDrivers();
73 /* No break: Initialize the index for first thread. */
75 /* The attached process creates a new thread. */
76 case DLL_THREAD_ATTACH
:
77 lpData
= (GLTHREADDATA
*)LocalAlloc(LPTR
, sizeof(GLTHREADDATA
));
80 memset ( lpData
, 0, sizeof(GLTHREADDATA
) );
81 (void)TlsSetValue ( OPENGL32_tls
, lpData
);
85 /* FIXME - defaulting to mesa3d, but shouldn't */
86 lpData
->list
= OPENGL32_processdata
.list
[0];
90 /* The thread of the attached process terminates. */
91 case DLL_THREAD_DETACH
:
92 /* Release the allocated memory for this thread.*/
93 OPENGL32_ThreadDetach();
96 /* DLL unload due to process termination or FreeLibrary. */
97 case DLL_PROCESS_DETACH
:
98 OPENGL32_ThreadDetach();
99 /* FIXME: free resources */
100 TlsFree(OPENGL32_tls
);
107 /* FUNCTION: Append ICD to linked list.
108 * ARGUMENTS: [IN] icd: GLDRIVERDATA to append to list
109 * TODO: protect from race conditions
111 static void OPENGL32_AppendICD( GLDRIVERDATA
*icd
)
113 if (!OPENGL32_processdata
.driver_list
)
114 OPENGL32_processdata
.driver_list
= icd
;
117 GLDRIVERDATA
*p
= OPENGL32_processdata
.driver_list
;
125 /* FUNCTION: Remove ICD from linked list.
126 * ARGUMENTS: [IN] icd: GLDRIVERDATA to remove from list
127 * TODO: protect from race conditions
129 static void OPENGL32_RemoveICD( GLDRIVERDATA
*icd
)
131 if (icd
== OPENGL32_processdata
.driver_list
)
132 OPENGL32_processdata
.driver_list
= icd
->next
;
135 GLDRIVERDATA
*p
= OPENGL32_processdata
.driver_list
;
145 DBGPRINT( "RemoveICD: ICD 0x%08x not found in list!\n" );
149 /* FIXME - I'm assuming we want to return TRUE if we find at least *one* ICD */
150 static BOOL
OPENGL32_LoadDrivers()
152 const WCHAR
* OpenGLDrivers
= L
"SOFTWARE\\Microsoft\\Windows NT\\"
153 "CurrentVersion\\OpenGLDrivers\\";
158 /* FIXME - detect if we've already done this from another process */
159 /* FIXME - special-case load of MESA3D as generic implementation ICD. */
161 if ( ERROR_SUCCESS
!= RegOpenKeyW( HKEY_LOCAL_MACHINE
, OpenGLDrivers
, &hkey
) )
163 for ( i
= 0; RegEnumKeyW(hkey
,i
,name
,sizeof(name
)/sizeof(name
[0])) == ERROR_SUCCESS
; i
++ )
165 /* ignoring return value, because OPENGL32_LoadICD() is doing *all* the work... */
166 /* GLDRIVERDATA* gldd =*/ OPENGL32_LoadICD ( name
);
168 RegCloseKey ( hkey
);
175 /* FUNCTION: Load an ICD.
176 * ARGUMENTS: [IN] driver: Name of display driver.
177 * RETURNS: error code; ERROR_SUCCESS on success
179 * TODO: call SetLastError() where appropriate
181 static GLDRIVERDATA
*OPENGL32_LoadDriver ( LPCWSTR driver
)
184 WCHAR subKey
[1024] = L
"SOFTWARE\\Microsoft\\Windows NT\\"
185 "CurrentVersion\\OpenGLDrivers\\";
189 DWORD version
, driverVersion
, flags
; /* registry values */
193 DBGPRINT( "Loading driver %ws...\n", driver
);
195 /* open registry key */
196 wcsncat( subKey
, driver
, 1024 );
197 ret
= RegOpenKeyExW( HKEY_LOCAL_MACHINE
, subKey
, 0, KEY_READ
, &hKey
);
198 if (ret
!= ERROR_SUCCESS
)
200 DBGPRINT( "Error: Couldn't open registry key '%ws'\n", subKey
);
206 ret
= RegQueryValueExW( hKey
, L
"Dll", 0, &type
, (LPBYTE
)dll
, &size
);
207 if (ret
!= ERROR_SUCCESS
|| type
!= REG_SZ
)
209 DBGPRINT( "Error: Couldn't query Dll value or not a string\n" );
214 size
= sizeof (DWORD
);
215 ret
= RegQueryValueExW( hKey
, L
"Version", 0, &type
, (LPBYTE
)&version
, &size
);
216 if (ret
!= ERROR_SUCCESS
|| type
!= REG_DWORD
)
218 DBGPRINT( "Warning: Couldn't query Version value or not a DWORD\n" );
222 size
= sizeof (DWORD
);
223 ret
= RegQueryValueExW( hKey
, L
"DriverVersion", 0, &type
,
224 (LPBYTE
)&driverVersion
, &size
);
225 if (ret
!= ERROR_SUCCESS
|| type
!= REG_DWORD
)
227 DBGPRINT( "Warning: Couldn't query DriverVersion value or not a DWORD\n" );
231 size
= sizeof (DWORD
);
232 ret
= RegQueryValueExW( hKey
, L
"Flags", 0, &type
, (LPBYTE
)&flags
, &size
);
233 if (ret
!= ERROR_SUCCESS
|| type
!= REG_DWORD
)
235 DBGPRINT( "Warning: Couldn't query Flags value or not a DWORD\n" );
242 DBGPRINT( "Dll = %ws\n", dll
);
243 DBGPRINT( "Version = 0x%08x\n", version
);
244 DBGPRINT( "DriverVersion = 0x%08x\n", driverVersion
);
245 DBGPRINT( "Flags = 0x%08x\n", flags
);
247 /* allocate driver data */
248 icd
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof (GLDRIVERDATA
) );
251 DBGPRINT( "Error: Couldnt allocate GLDRIVERDATA!\n" );
254 wcsncpy( icd
->driver_name
, driver
, 256 );
255 wcsncpy( icd
->dll
, dll
, 256 );
256 icd
->version
= version
;
257 icd
->driver_version
= driverVersion
;
261 ret
= OPENGL32_InitializeDriver( icd
);
262 if (ret
!= ERROR_SUCCESS
)
264 if (!HeapFree( GetProcessHeap(), 0, icd
))
265 DBGPRINT( "Error: HeapFree() returned false, error code = %d\n",
267 DBGPRINT( "Error: Couldnt initialize ICD!\n" );
271 /* append ICD to list */
272 OPENGL32_AppendICD( icd
);
273 DBGPRINT( "ICD loaded.\n" );
279 /* FUNCTION: Initialize a driver (Load DLL, DrvXXX and glXXX procs)
280 * ARGUMENTS: [IN] icd: ICD to initialize with the dll, version, driverVersion
281 * and flags already filled.
282 * RETURNS: error code; ERROR_SUCCESS on success
284 #define LOAD_DRV_PROC( icd, proc, required ) \
285 icd->proc = GetProcAddress( icd->handle, #proc ); \
286 if (required && !icd->proc) { \
287 DBGPRINT( "Error: GetProcAddress(\"%s\") failed!", #proc ); \
288 return GetLastError(); \
291 static DWORD
OPENGL32_InitializeDriver( GLDRIVERDATA
*icd
)
296 icd
->handle
= LoadLibraryW( icd
->dll
);
299 DBGPRINT( "Error: Couldn't load DLL! (%d)\n", GetLastError() );
300 return GetLastError();
303 /* load DrvXXX procs */
304 LOAD_DRV_PROC(icd
, DrvCopyContext
, TRUE
);
305 LOAD_DRV_PROC(icd
, DrvCreateContext
, TRUE
);
306 LOAD_DRV_PROC(icd
, DrvCreateLayerContext
, TRUE
);
307 LOAD_DRV_PROC(icd
, DrvDeleteContext
, TRUE
);
308 LOAD_DRV_PROC(icd
, DrvDescribeLayerPlane
, TRUE
);
309 LOAD_DRV_PROC(icd
, DrvDescribePixelFormat
, TRUE
);
310 LOAD_DRV_PROC(icd
, DrvGetLayerPaletteEntries
, TRUE
);
311 LOAD_DRV_PROC(icd
, DrvGetProcAddress
, TRUE
);
312 LOAD_DRV_PROC(icd
, DrvReleaseContext
, TRUE
);
313 LOAD_DRV_PROC(icd
, DrvRealizeLayerPalette
, TRUE
);
314 LOAD_DRV_PROC(icd
, DrvSetContext
, TRUE
);
315 LOAD_DRV_PROC(icd
, DrvSetLayerPaletteEntries
, TRUE
);
316 LOAD_DRV_PROC(icd
, DrvSetPixelFormat
, TRUE
);
317 LOAD_DRV_PROC(icd
, DrvShareLists
, TRUE
);
318 LOAD_DRV_PROC(icd
, DrvSwapBuffers
, TRUE
);
319 LOAD_DRV_PROC(icd
, DrvSwapLayerBuffers
, TRUE
);
320 LOAD_DRV_PROC(icd
, DrvValidateVersion
, TRUE
);
322 /* now load the glXXX functions */
323 for (i
= 0; i
< GLIDX_COUNT
; i
++)
325 icd
->func_list
[i
] = icd
->DrvGetProcAddress( OPENGL32_funcnames
[i
] );
326 #ifdef DEBUG_OPENGL32_ICD_EXPORTS
327 if ( icd
->func_list
[i
] )
329 DBGPRINT( "Found function %s in ICD.\n", OPENGL32_funcnames
[i
] );
334 return ERROR_SUCCESS
;
338 /* FUNCTION: Unload loaded ICD.
339 * RETURNS: TRUE on success, FALSE otherwise.
341 static BOOL
OPENGL32_UnloadDriver( GLDRIVERDATA
*icd
)
345 DBGPRINT( "Unloading driver %ws...\n", icd
->driver_name
);
347 DBGPRINT( "Warning: ICD refcount = %d (should be 0)\n", icd
->refcount
);
350 if (!FreeLibrary( icd
->handle
))
353 DBGPRINT( "Warning: FreeLibrary on ICD %ws failed!\n", icd
->dll
);
357 OPENGL32_RemoveICD( icd
);
358 HeapFree( GetProcessHeap(), 0, icd
);
364 /* FUNCTION: Load ICD (shared ICD data)
365 * RETURNS: GLDRIVERDATA pointer on success, NULL otherwise.
367 GLDRIVERDATA
*OPENGL32_LoadICD ( LPCWSTR driver
)
371 /* look if ICD is already loaded */
372 for (icd
= OPENGL32_processdata
.driver_list
; icd
; icd
= icd
->next
)
374 if (!_wcsicmp( driver
, icd
->driver_name
)) /* found */
381 /* not found - try to load */
382 icd
= OPENGL32_LoadDriver ( driver
);
389 /* FUNCTION: Unload ICD (shared ICD data)
390 * RETURNS: TRUE on success, FALSE otherwise.
392 BOOL
OPENGL32_UnloadICD( GLDRIVERDATA
*icd
)
395 if (icd
->refcount
== 0)
396 return OPENGL32_UnloadDriver( icd
);