Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenopengl32.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS kernel 00004 * FILE: lib/opengl32/opengl32.c 00005 * PURPOSE: OpenGL32 lib 00006 * PROGRAMMER: Anich Gregor (blight), Royce Mitchell III 00007 * UPDATE HISTORY: 00008 * Feb 1, 2004: Created 00009 */ 00010 00011 #include "opengl32.h" 00012 00013 /* function prototypes */ 00014 static void OPENGL32_AppendICD( GLDRIVERDATA *icd ); 00015 static void OPENGL32_RemoveICD( GLDRIVERDATA *icd ); 00016 static GLDRIVERDATA *OPENGL32_LoadDriver( LPCWSTR regKey ); 00017 static DWORD OPENGL32_InitializeDriver( GLDRIVERDATA *icd ); 00018 static BOOL OPENGL32_UnloadDriver( GLDRIVERDATA *icd ); 00019 static DWORD OPENGL32_RegGetDriverInfo( LPCWSTR driver, GLDRIVERDATA *icd ); 00020 00021 00022 /* global vars */ 00023 /* Do not assume it have the free value MAXDWORD set, any value can be in here */ 00024 DWORD OPENGL32_tls = MAXDWORD; 00025 GLPROCESSDATA OPENGL32_processdata; 00026 00027 00028 static BOOL 00029 OPENGL32_ThreadAttach( void ) 00030 { 00031 GLTHREADDATA* lpData = NULL; 00032 PROC *dispatchTable = NULL; 00033 TEB *teb = NULL; 00034 00035 dispatchTable = (PROC*)HeapAlloc( GetProcessHeap(), 00036 HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY, 00037 DISPATCH_TABLE_SIZE ); 00038 if (dispatchTable == NULL) 00039 { 00040 DBGPRINT( "Error: Couldn't allocate GL dispatch table" ); 00041 return FALSE; 00042 } 00043 00044 lpData = (GLTHREADDATA*)HeapAlloc( GetProcessHeap(), 00045 HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY, 00046 sizeof (GLTHREADDATA) ); 00047 if (lpData == NULL) 00048 { 00049 DBGPRINT( "Error: Couldn't allocate GLTHREADDATA" ); 00050 HeapFree( GetProcessHeap(), 0, dispatchTable ); 00051 return FALSE; 00052 } 00053 00054 teb = NtCurrentTeb(); 00055 00056 /* initialize dispatch table with empty functions */ 00057 #define X(func, ret, typeargs, args, icdidx, tebidx, stack) \ 00058 dispatchTable[icdidx] = (PROC)glEmptyFunc##stack; \ 00059 if (tebidx >= 0) \ 00060 teb->glDispatchTable[tebidx] = (PVOID)glEmptyFunc##stack; 00061 GLFUNCS_MACRO 00062 #undef X 00063 00064 teb->glTable = dispatchTable; 00065 TlsSetValue( OPENGL32_tls, lpData ); 00066 00067 return TRUE; 00068 } 00069 00070 00071 static void 00072 OPENGL32_ThreadDetach( void ) 00073 { 00074 GLTHREADDATA* lpData = NULL; 00075 TEB* teb = NtCurrentTeb(); 00076 00077 rosglMakeCurrent( NULL, NULL ); 00078 00079 lpData = (GLTHREADDATA*)TlsGetValue( OPENGL32_tls ); 00080 if (lpData != NULL) 00081 { 00082 if (!HeapFree( GetProcessHeap(), 0, lpData )) 00083 DBGPRINT( "Warning: HeapFree() on GLTHREADDATA failed (%d)", 00084 GetLastError() ); 00085 lpData = NULL; 00086 } 00087 TlsSetValue( OPENGL32_tls, NULL ); 00088 00089 if (teb->glTable != NULL) 00090 { 00091 if (!HeapFree( GetProcessHeap(), 0, teb->glTable )) 00092 { 00093 DBGPRINT( "Warning: HeapFree() on dispatch table failed (%d)", 00094 GetLastError() ); 00095 } 00096 /* NULL-ify it. Even if something went wrong, it's not a good idea to keep it non NULL */ 00097 teb->glTable = NULL; 00098 } 00099 } 00100 00101 00102 static BOOL 00103 OPENGL32_ProcessAttach( void ) 00104 { 00105 SECURITY_ATTRIBUTES attrib = { sizeof (SECURITY_ATTRIBUTES), /* nLength */ 00106 NULL, /* lpSecurityDescriptor */ 00107 TRUE /* bInheritHandle */ }; 00108 00109 OPENGL32_tls = TlsAlloc(); 00110 if (OPENGL32_tls == MAXDWORD) 00111 return FALSE; 00112 00113 memset( &OPENGL32_processdata, 0, sizeof (OPENGL32_processdata) ); 00114 00115 /* create driver, glrc & dcdata list mutex */ 00116 OPENGL32_processdata.driver_mutex = CreateMutex( &attrib, FALSE, NULL ); 00117 if (OPENGL32_processdata.driver_mutex == NULL) 00118 { 00119 DBGPRINT( "Error: Couldn't create driver_list mutex (%d)", 00120 GetLastError() ); 00121 return FALSE; 00122 } 00123 OPENGL32_processdata.glrc_mutex = CreateMutex( &attrib, FALSE, NULL ); 00124 if (OPENGL32_processdata.glrc_mutex == NULL) 00125 { 00126 DBGPRINT( "Error: Couldn't create glrc_list mutex (%d)", 00127 GetLastError() ); 00128 return FALSE; 00129 } 00130 OPENGL32_processdata.dcdata_mutex = CreateMutex( &attrib, FALSE, NULL ); 00131 if (OPENGL32_processdata.dcdata_mutex == NULL) 00132 { 00133 DBGPRINT( "Error: Couldn't create dcdata_list mutex (%d)", 00134 GetLastError() ); 00135 return FALSE; 00136 } 00137 00138 return TRUE; 00139 } 00140 00141 00142 static void 00143 OPENGL32_ProcessDetach( void ) 00144 { 00145 GLDRIVERDATA *icd, *icd2; 00146 GLDCDATA *dcdata, *dcdata2; 00147 GLRC *glrc, *glrc2; 00148 00149 /* free lists */ 00150 for (dcdata = OPENGL32_processdata.dcdata_list; dcdata != NULL;) 00151 { 00152 dcdata2 = dcdata; 00153 dcdata = dcdata->next; 00154 if (!HeapFree( GetProcessHeap(), 0, dcdata2 )) 00155 DBGPRINT( "Warning: HeapFree() on DCDATA 0x%08x failed (%d)", 00156 dcdata2, GetLastError() ); 00157 } 00158 00159 for (glrc = OPENGL32_processdata.glrc_list; glrc != NULL;) 00160 { 00161 glrc2 = glrc; 00162 glrc = glrc->next; 00163 if (!HeapFree( GetProcessHeap(), 0, glrc2 )) 00164 DBGPRINT( "Warning: HeapFree() on GLRC 0x%08x failed (%d)", 00165 glrc2, GetLastError() ); 00166 } 00167 00168 for (icd = OPENGL32_processdata.driver_list; icd != NULL;) 00169 { 00170 icd2 = icd; 00171 icd = icd->next; 00172 if (!HeapFree( GetProcessHeap(), 0, icd2 )) 00173 DBGPRINT( "Warning: HeapFree() on DRIVERDATA 0x%08x failed (%d)", 00174 icd2, GetLastError() ); 00175 } 00176 00177 /* free mutexes */ 00178 if (OPENGL32_processdata.driver_mutex != NULL) 00179 CloseHandle( OPENGL32_processdata.driver_mutex ); 00180 if (OPENGL32_processdata.glrc_mutex != NULL) 00181 CloseHandle( OPENGL32_processdata.glrc_mutex ); 00182 if (OPENGL32_processdata.dcdata_mutex != NULL) 00183 CloseHandle( OPENGL32_processdata.dcdata_mutex ); 00184 00185 /* free TLS */ 00186 if (OPENGL32_tls != MAXDWORD) 00187 TlsFree(OPENGL32_tls); 00188 } 00189 00190 00191 BOOL WINAPI 00192 DllMain(HINSTANCE hInstance, DWORD Reason, LPVOID Reserved) 00193 { 00194 DBGPRINT( "Info: Called!" ); 00195 switch ( Reason ) 00196 { 00197 /* The DLL is loading due to process 00198 * initialization or a call to LoadLibrary. 00199 */ 00200 case DLL_PROCESS_ATTACH: 00201 DBGTRACE( "Process attach" ); 00202 if (!OPENGL32_ProcessAttach()) 00203 return FALSE; 00204 /* No break: Initialize the index for first thread. */ 00205 00206 /* The attached process creates a new thread. */ 00207 case DLL_THREAD_ATTACH: 00208 DBGTRACE( "Thread attach" ); 00209 if (!OPENGL32_ThreadAttach()) 00210 return FALSE; 00211 break; 00212 00213 /* The thread of the attached process terminates. */ 00214 case DLL_THREAD_DETACH: 00215 DBGTRACE( "Thread detach" ); 00216 /* Release the allocated memory for this thread.*/ 00217 OPENGL32_ThreadDetach(); 00218 break; 00219 00220 /* DLL unload due to process termination or FreeLibrary. */ 00221 case DLL_PROCESS_DETACH: 00222 DBGTRACE( "Process detach" ); 00223 OPENGL32_ThreadDetach(); 00224 OPENGL32_ProcessDetach(); 00225 break; 00226 } 00227 00228 return TRUE; 00229 } 00230 00231 00238 static void 00239 OPENGL32_AppendICD( GLDRIVERDATA *icd ) 00240 { 00241 if (OPENGL32_processdata.driver_list == NULL) 00242 OPENGL32_processdata.driver_list = icd; 00243 else 00244 { 00245 GLDRIVERDATA *p = OPENGL32_processdata.driver_list; 00246 while (p->next != NULL) 00247 p = p->next; 00248 p->next = icd; 00249 } 00250 } 00251 00252 00259 static void 00260 OPENGL32_RemoveICD( GLDRIVERDATA *icd ) 00261 { 00262 if (icd == OPENGL32_processdata.driver_list) 00263 OPENGL32_processdata.driver_list = icd->next; 00264 else 00265 { 00266 GLDRIVERDATA *p = OPENGL32_processdata.driver_list; 00267 while (p != NULL) 00268 { 00269 if (p->next == icd) 00270 { 00271 p->next = icd->next; 00272 return; 00273 } 00274 p = p->next; 00275 } 00276 DBGPRINT( "Error: ICD 0x%08x not found in list!", icd ); 00277 } 00278 } 00279 00280 00290 static GLDRIVERDATA * 00291 OPENGL32_LoadDriver( LPCWSTR driver ) 00292 { 00293 LONG ret; 00294 GLDRIVERDATA *icd; 00295 00296 DBGPRINT( "Info: Loading driver %ws...", driver ); 00297 00298 /* allocate driver data */ 00299 icd = (GLDRIVERDATA*)HeapAlloc( GetProcessHeap(), 00300 HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY, 00301 sizeof (GLDRIVERDATA) ); 00302 if (icd == NULL) 00303 { 00304 DBGPRINT( "Error: Couldn't allocate GLDRIVERDATA! (%d)", GetLastError() ); 00305 return NULL; 00306 } 00307 00308 ret = OPENGL32_RegGetDriverInfo( driver, icd ); 00309 if (ret != ERROR_SUCCESS) 00310 { 00311 DBGPRINT( "Error: Couldn't query driver information (%d)", ret ); 00312 if (!HeapFree( GetProcessHeap(), 0, icd )) 00313 DBGPRINT( "Error: HeapFree() returned false, error code = %d", 00314 GetLastError() ); 00315 return NULL; 00316 } 00317 00318 DBGPRINT( "Info: Dll = %ws", icd->dll ); 00319 DBGPRINT( "Info: Version = 0x%08x", icd->version ); 00320 DBGPRINT( "Info: DriverVersion = 0x%08x", icd->driver_version ); 00321 DBGPRINT( "Info: Flags = 0x%08x", icd->flags ); 00322 00323 /* load/initialize ICD */ 00324 ret = OPENGL32_InitializeDriver( icd ); 00325 if (ret != ERROR_SUCCESS) 00326 { 00327 DBGPRINT( "Error: Couldnt initialize ICD!" ); 00328 if (!HeapFree( GetProcessHeap(), 0, icd )) 00329 DBGPRINT( "Error: HeapFree() returned false, error code = %d", 00330 GetLastError() ); 00331 return NULL; 00332 } 00333 00334 /* append ICD to list */ 00335 OPENGL32_AppendICD( icd ); 00336 DBGPRINT( "Info: ICD loaded." ); 00337 00338 return icd; 00339 } 00340 00341 00349 #define LOAD_DRV_PROC( icd, proc, required ) \ 00350 *(char**)&icd->proc = (char*)GetProcAddress( icd->handle, #proc ); \ 00351 if (required && icd->proc == NULL) { \ 00352 DBGPRINT( "Error: GetProcAddress(\"%s\") failed!", #proc ); \ 00353 FreeLibrary( icd->handle ); \ 00354 return GetLastError(); \ 00355 } 00356 00357 static DWORD 00358 OPENGL32_InitializeDriver( GLDRIVERDATA *icd ) 00359 { 00360 /* check version */ 00361 if (icd->version > 2) 00362 DBGPRINT( "Warning: ICD version > 2 (%d)", icd->version ); 00363 00364 /* load dll */ 00365 icd->handle = LoadLibraryW( icd->dll ); 00366 if (icd->handle == NULL) 00367 { 00368 DWORD err = GetLastError(); 00369 DBGPRINT( "Error: Couldn't load DLL! (%d)", err ); 00370 return err; 00371 } 00372 00373 /* validate version */ 00374 if (icd->driver_version > 1) 00375 { 00376 LOAD_DRV_PROC(icd, DrvValidateVersion, FALSE); 00377 if (icd->DrvValidateVersion != NULL) 00378 { 00379 if (!icd->DrvValidateVersion( icd->driver_version )) 00380 { 00381 DBGPRINT( "Error: DrvValidateVersion failed!" ); 00382 DBGBREAK(); 00383 FreeLibrary( icd->handle ); 00384 return ERROR_INVALID_FUNCTION; /* FIXME: use better error code */ 00385 } 00386 } 00387 else 00388 DBGPRINT( "Info: DrvValidateVersion not exported by ICD" ); 00389 } 00390 00391 /* load DrvXXX procs */ 00392 LOAD_DRV_PROC(icd, DrvCopyContext, TRUE); 00393 LOAD_DRV_PROC(icd, DrvCreateContext, FALSE); 00394 LOAD_DRV_PROC(icd, DrvCreateLayerContext, FALSE); 00395 LOAD_DRV_PROC(icd, DrvDeleteContext, TRUE); 00396 LOAD_DRV_PROC(icd, DrvDescribeLayerPlane, TRUE); 00397 LOAD_DRV_PROC(icd, DrvDescribePixelFormat, TRUE); 00398 LOAD_DRV_PROC(icd, DrvGetLayerPaletteEntries, TRUE); 00399 LOAD_DRV_PROC(icd, DrvGetProcAddress, TRUE); 00400 LOAD_DRV_PROC(icd, DrvReleaseContext, TRUE); 00401 LOAD_DRV_PROC(icd, DrvRealizeLayerPalette, TRUE); 00402 LOAD_DRV_PROC(icd, DrvSetContext, TRUE); 00403 LOAD_DRV_PROC(icd, DrvSetLayerPaletteEntries, TRUE); 00404 LOAD_DRV_PROC(icd, DrvSetPixelFormat, TRUE); 00405 LOAD_DRV_PROC(icd, DrvShareLists, TRUE); 00406 LOAD_DRV_PROC(icd, DrvSwapBuffers, TRUE); 00407 LOAD_DRV_PROC(icd, DrvSwapLayerBuffers, TRUE); 00408 00409 /* we require at least one of DrvCreateContext and DrvCreateLayerContext */ 00410 if (icd->DrvCreateContext == NULL && icd->DrvCreateLayerContext == NULL) 00411 { 00412 DBGPRINT( "Error: One of DrvCreateContext/DrvCreateLayerContext is required!" ); 00413 FreeLibrary( icd->handle ); 00414 return ERROR_INVALID_FUNCTION; /* FIXME: use better error code... */ 00415 } 00416 00417 return ERROR_SUCCESS; 00418 } 00419 00420 00426 static BOOL 00427 OPENGL32_UnloadDriver( GLDRIVERDATA *icd ) 00428 { 00429 BOOL allOk = TRUE; 00430 00431 DBGPRINT( "Info: Unloading driver %ws...", icd->driver_name ); 00432 if (icd->refcount != 0) 00433 DBGPRINT( "Warning: ICD refcount = %d (should be 0)", icd->refcount ); 00434 00435 /* unload dll */ 00436 if (!FreeLibrary( icd->handle )) 00437 { 00438 allOk = FALSE; 00439 DBGPRINT( "Warning: FreeLibrary on ICD %ws failed! (%d)", icd->dll, 00440 GetLastError() ); 00441 } 00442 00443 /* free resources */ 00444 OPENGL32_RemoveICD( icd ); 00445 if (!HeapFree( GetProcessHeap(), 0, icd )) 00446 { 00447 allOk = FALSE; 00448 DBGPRINT( "Warning: HeapFree() returned FALSE, error code = %d", 00449 GetLastError() ); 00450 } 00451 00452 return allOk; 00453 } 00454 00455 00461 GLDRIVERDATA * 00462 OPENGL32_LoadICD( LPCWSTR driver ) 00463 { 00464 GLDRIVERDATA *icd; 00465 00466 /* synchronize */ 00467 if (WaitForSingleObject( OPENGL32_processdata.driver_mutex, INFINITE ) == 00468 WAIT_FAILED) 00469 { 00470 DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() ); 00471 return NULL; /* FIXME: do we have to expect such an error and handle it? */ 00472 } 00473 00474 /* look if ICD is already loaded */ 00475 for (icd = OPENGL32_processdata.driver_list; icd; icd = icd->next) 00476 { 00477 if (!_wcsicmp( driver, icd->driver_name )) /* found */ 00478 { 00479 /* release mutex */ 00480 if (!ReleaseMutex( OPENGL32_processdata.driver_mutex )) 00481 DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() ); 00482 00483 return icd; 00484 } 00485 } 00486 00487 /* not found - try to load */ 00488 icd = OPENGL32_LoadDriver( driver ); 00489 00490 /* release mutex */ 00491 if (!ReleaseMutex( OPENGL32_processdata.driver_mutex )) 00492 DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() ); 00493 00494 return icd; 00495 } 00496 00497 00503 BOOL 00504 OPENGL32_UnloadICD( GLDRIVERDATA *icd ) 00505 { 00506 BOOL ret = TRUE; 00507 00508 /* synchronize */ 00509 if (WaitForSingleObject( OPENGL32_processdata.driver_mutex, INFINITE ) == 00510 WAIT_FAILED) 00511 { 00512 DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() ); 00513 return FALSE; /* FIXME: do we have to expect such an error and handle it? */ 00514 } 00515 00516 if (icd->refcount == 0) 00517 ret = OPENGL32_UnloadDriver( icd ); 00518 00519 /* release mutex */ 00520 if (!ReleaseMutex( OPENGL32_processdata.driver_mutex )) 00521 DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() ); 00522 00523 return ret; 00524 } 00525 00526 00539 #if 0 /* unused */ 00540 DWORD 00541 OPENGL32_RegEnumDrivers( DWORD idx, LPWSTR name, LPDWORD cName ) 00542 { 00543 HKEY hKey; 00544 LPCWSTR subKey = OPENGL_DRIVERS_SUBKEY; 00545 LONG ret; 00546 DWORD size; 00547 WCHAR driver[256]; 00548 00549 if (name == NULL) 00550 return ERROR_SUCCESS; /* nothing to do */ 00551 00552 if (cName == NULL) 00553 return ERROR_INVALID_FUNCTION; /* we need cName when name is given */ 00554 00555 /* open OpenGLDrivers registry key */ 00556 ret = RegOpenKeyExW( HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, &hKey ); 00557 if (ret != ERROR_SUCCESS) 00558 { 00559 DBGPRINT( "Error: Couldn't open registry key '%ws'", subKey ); 00560 return ret; 00561 } 00562 00563 /* get subkey name */ 00564 size = sizeof (driver) / sizeof (driver[0]); 00565 ret = RegEnumKeyW( hKey, idx, name, *cName ); 00566 if (ret != ERROR_SUCCESS) 00567 { 00568 DBGPRINT( "Error: Couldn't get OpenGLDrivers subkey name (%d)", ret ); 00569 RegCloseKey( hKey ); 00570 return ret; 00571 } 00572 *cName = wcslen( name ); 00573 00574 /* close key */ 00575 RegCloseKey( hKey ); 00576 return ERROR_SUCCESS; 00577 } 00578 #endif /* 0 -- unused */ 00579 00580 00592 static DWORD 00593 OPENGL32_RegGetDriverInfo( LPCWSTR driver, GLDRIVERDATA *icd ) 00594 { 00595 HKEY hKey; 00596 WCHAR subKey[1024] = OPENGL_DRIVERS_SUBKEY2; 00597 LONG ret; 00598 DWORD type, size; 00599 00600 /* drivers registry values */ 00601 DWORD version = 1, driverVersion = 0, flags = 0; 00602 WCHAR dll[256]; 00603 00604 /* open driver registry key */ 00605 wcsncat( subKey, driver, 1024 ); 00606 ret = RegOpenKeyExW( HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, &hKey ); 00607 if (ret != ERROR_SUCCESS) 00608 { 00609 DBGPRINT( "Error: Couldn't open registry key '%ws'", subKey ); 00610 return ret; 00611 } 00612 00613 /* query values */ 00614 size = sizeof (dll); 00615 ret = RegQueryValueExW( hKey, L"Dll", 0, &type, (LPBYTE)dll, &size ); 00616 if (ret != ERROR_SUCCESS || type != REG_SZ) 00617 { 00618 DBGPRINT( "Error: Couldn't query Dll value or not a string" ); 00619 RegCloseKey( hKey ); 00620 return ret; 00621 } 00622 00623 size = sizeof (DWORD); 00624 ret = RegQueryValueExW( hKey, L"Version", 0, &type, (LPBYTE)&version, &size ); 00625 if (ret != ERROR_SUCCESS || type != REG_DWORD) 00626 DBGPRINT( "Warning: Couldn't query Version value or not a DWORD" ); 00627 00628 size = sizeof (DWORD); 00629 ret = RegQueryValueExW( hKey, L"DriverVersion", 0, &type, 00630 (LPBYTE)&driverVersion, &size ); 00631 if (ret != ERROR_SUCCESS || type != REG_DWORD) 00632 DBGPRINT( "Warning: Couldn't query DriverVersion value or not a DWORD" ); 00633 00634 size = sizeof (DWORD); 00635 ret = RegQueryValueExW( hKey, L"Flags", 0, &type, (LPBYTE)&flags, &size ); 00636 if (ret != ERROR_SUCCESS || type != REG_DWORD) 00637 DBGPRINT( "Warning: Couldn't query Flags value or not a DWORD" ); 00638 00639 /* close key */ 00640 RegCloseKey( hKey ); 00641 00642 /* output data */ 00643 /* FIXME: NUL-terminate strings? */ 00644 wcsncpy( icd->driver_name, driver, 00645 sizeof (icd->driver_name) / sizeof (icd->driver_name[0]) - 1 ); 00646 wcsncpy( icd->dll, dll, 00647 sizeof (icd->dll) / sizeof (icd->dll[0]) ); 00648 icd->version = version; 00649 icd->driver_version = driverVersion; 00650 icd->flags = flags; 00651 00652 return ERROR_SUCCESS; 00653 } 00654 00655 /* EOF */ 00656 Generated on Sat May 26 2012 04:24:27 for ReactOS by
1.7.6.1
|