📄 opengl32.c
字号:
}
/* append ICD to list */
OPENGL32_AppendICD( icd );
DBGPRINT( "Info: ICD loaded." );
return icd;
}
/*! \brief Initialize a driver (Load DLL and DrvXxx procs)
*
* \param icd ICD to initialize with the dll, version, driverVersion
* and flags already filled.
* \return Error code.
* \retval ERROR_SUCCESS Success
*/
#define LOAD_DRV_PROC( icd, proc, required ) \
*(char**)&icd->proc = (char*)GetProcAddress( icd->handle, #proc ); \
if (required && icd->proc == NULL) { \
DBGPRINT( "Error: GetProcAddress(\"%s\") failed!", #proc ); \
FreeLibrary( icd->handle ); \
return GetLastError(); \
}
static DWORD
OPENGL32_InitializeDriver( GLDRIVERDATA *icd )
{
/* check version */
if (icd->version > 2)
DBGPRINT( "Warning: ICD version > 2 (%d)", icd->version );
/* load dll */
icd->handle = LoadLibraryW( icd->dll );
if (icd->handle == NULL)
{
DWORD err = GetLastError();
DBGPRINT( "Error: Couldn't load DLL! (%d)", err );
return err;
}
/* validate version */
if (icd->driver_version > 1)
{
LOAD_DRV_PROC(icd, DrvValidateVersion, FALSE);
if (icd->DrvValidateVersion != NULL)
{
if (!icd->DrvValidateVersion( icd->driver_version ))
{
DBGPRINT( "Error: DrvValidateVersion failed!" );
DBGBREAK();
FreeLibrary( icd->handle );
return ERROR_INVALID_FUNCTION; /* FIXME: use better error code */
}
}
else
DBGPRINT( "Info: DrvValidateVersion not exported by ICD" );
}
/* load DrvXXX procs */
LOAD_DRV_PROC(icd, DrvCopyContext, TRUE);
LOAD_DRV_PROC(icd, DrvCreateContext, FALSE);
LOAD_DRV_PROC(icd, DrvCreateLayerContext, FALSE);
LOAD_DRV_PROC(icd, DrvDeleteContext, TRUE);
LOAD_DRV_PROC(icd, DrvDescribeLayerPlane, TRUE);
LOAD_DRV_PROC(icd, DrvDescribePixelFormat, TRUE);
LOAD_DRV_PROC(icd, DrvGetLayerPaletteEntries, TRUE);
LOAD_DRV_PROC(icd, DrvGetProcAddress, TRUE);
LOAD_DRV_PROC(icd, DrvReleaseContext, TRUE);
LOAD_DRV_PROC(icd, DrvRealizeLayerPalette, TRUE);
LOAD_DRV_PROC(icd, DrvSetContext, TRUE);
LOAD_DRV_PROC(icd, DrvSetLayerPaletteEntries, TRUE);
LOAD_DRV_PROC(icd, DrvSetPixelFormat, TRUE);
LOAD_DRV_PROC(icd, DrvShareLists, TRUE);
LOAD_DRV_PROC(icd, DrvSwapBuffers, TRUE);
LOAD_DRV_PROC(icd, DrvSwapLayerBuffers, TRUE);
/* we require at least one of DrvCreateContext and DrvCreateLayerContext */
if (icd->DrvCreateContext == NULL && icd->DrvCreateLayerContext == NULL)
{
DBGPRINT( "Error: One of DrvCreateContext/DrvCreateLayerContext is required!" );
FreeLibrary( icd->handle );
return ERROR_INVALID_FUNCTION; /* FIXME: use better error code... */
}
return ERROR_SUCCESS;
}
/*! \brief Unload ICD.
*
* \retval TRUE Success.
* \retval FALSE Failure.
*/
static BOOL
OPENGL32_UnloadDriver( GLDRIVERDATA *icd )
{
BOOL allOk = TRUE;
DBGPRINT( "Info: Unloading driver %ws...", icd->driver_name );
if (icd->refcount != 0)
DBGPRINT( "Warning: ICD refcount = %d (should be 0)", icd->refcount );
/* unload dll */
if (!FreeLibrary( icd->handle ))
{
allOk = FALSE;
DBGPRINT( "Warning: FreeLibrary on ICD %ws failed! (%d)", icd->dll,
GetLastError() );
}
/* free resources */
OPENGL32_RemoveICD( icd );
if (!HeapFree( GetProcessHeap(), 0, icd ))
{
allOk = FALSE;
DBGPRINT( "Warning: HeapFree() returned FALSE, error code = %d",
GetLastError() );
}
return allOk;
}
/*! \brief Load ICD (shared ICD data)
*
* \return Pointer to an allocated GLDRIVERDATA on success.
* \retval NULL Failure.
*/
GLDRIVERDATA *
OPENGL32_LoadICD( LPCWSTR driver )
{
GLDRIVERDATA *icd;
/* synchronize */
if (WaitForSingleObject( OPENGL32_processdata.driver_mutex, INFINITE ) ==
WAIT_FAILED)
{
DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
return NULL; /* FIXME: do we have to expect such an error and handle it? */
}
/* look if ICD is already loaded */
for (icd = OPENGL32_processdata.driver_list; icd; icd = icd->next)
{
if (!_wcsicmp( driver, icd->driver_name )) /* found */
{
icd->refcount++;
/* release mutex */
if (!ReleaseMutex( OPENGL32_processdata.driver_mutex ))
DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
return icd;
}
}
/* not found - try to load */
icd = OPENGL32_LoadDriver( driver );
if (icd != NULL)
icd->refcount = 1;
/* release mutex */
if (!ReleaseMutex( OPENGL32_processdata.driver_mutex ))
DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
return icd;
}
/*! \brief Unload ICD (shared ICD data)
*
* \retval TRUE Success.
* \retval FALSE Failure.
*/
BOOL
OPENGL32_UnloadICD( GLDRIVERDATA *icd )
{
BOOL ret = TRUE;
/* synchronize */
if (WaitForSingleObject( OPENGL32_processdata.driver_mutex, INFINITE ) ==
WAIT_FAILED)
{
DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
return FALSE; /* FIXME: do we have to expect such an error and handle it? */
}
icd->refcount--;
if (icd->refcount == 0)
// if (0)
ret = OPENGL32_UnloadDriver( icd );
/* FIXME: InitializeICD crashes when called a second time */
/* release mutex */
if (!ReleaseMutex( OPENGL32_processdata.driver_mutex ))
DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
return ret;
}
/*! \brief Enumerate OpenGLDrivers (from registry)
*
* \param idx Index of the driver to get information about.
* \param name Pointer to an array of WCHARs (can be NULL)
* \param cName Pointer to a DWORD. Input is len of name array.
* Output is length of the drivername.
* Can be NULL if name is NULL.
*
* \return Error code
* \retval ERROR_NO_MORE_ITEMS End of driver list.
* \retval ERROR_SUCCESS Success.
*/
#if 0 /* unused */
DWORD
OPENGL32_RegEnumDrivers( DWORD idx, LPWSTR name, LPDWORD cName )
{
HKEY hKey;
LPCWSTR subKey = OPENGL_DRIVERS_SUBKEY;
LONG ret;
DWORD size;
WCHAR driver[256];
if (name == NULL)
return ERROR_SUCCESS; /* nothing to do */
if (cName == NULL)
return ERROR_INVALID_FUNCTION; /* we need cName when name is given */
/* open OpenGLDrivers registry key */
ret = RegOpenKeyExW( HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, &hKey );
if (ret != ERROR_SUCCESS)
{
DBGPRINT( "Error: Couldn't open registry key '%ws'", subKey );
return ret;
}
/* get subkey name */
size = sizeof (driver) / sizeof (driver[0]);
ret = RegEnumKeyW( hKey, idx, name, *cName );
if (ret != ERROR_SUCCESS)
{
DBGPRINT( "Error: Couldn't get OpenGLDrivers subkey name (%d)", ret );
RegCloseKey( hKey );
return ret;
}
*cName = wcslen( name );
/* close key */
RegCloseKey( hKey );
return ERROR_SUCCESS;
}
#endif /* 0 -- unused */
/*! \brief Get registry values for a driver given a name.
*
* \param driver Name of the driver to get information about.
* \param icd Pointer to GLDRIVERDATA.
*
* \return Error code.
* \retval ERROR_SUCCESS Success.
*
* \note On success the following fields of \a icd are filled: \a driver_name,
* \a dll, \a version, \a driver_version and \a flags.
*/
static DWORD
OPENGL32_RegGetDriverInfo( LPCWSTR driver, GLDRIVERDATA *icd )
{
HKEY hKey;
WCHAR subKey[1024] = OPENGL_DRIVERS_SUBKEY"\\";
LONG ret;
DWORD type, size;
/* drivers registry values */
DWORD version = 1, driverVersion = 0, flags = 0;
WCHAR dll[256];
/* open driver registry key */
wcsncat( subKey, driver, 1024 );
ret = RegOpenKeyExW( HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, &hKey );
if (ret != ERROR_SUCCESS)
{
DBGPRINT( "Error: Couldn't open registry key '%ws'", subKey );
return ret;
}
/* query values */
size = sizeof (dll);
ret = RegQueryValueExW( hKey, L"Dll", 0, &type, (LPBYTE)dll, &size );
if (ret != ERROR_SUCCESS || type != REG_SZ)
{
DBGPRINT( "Error: Couldn't query Dll value or not a string" );
RegCloseKey( hKey );
return ret;
}
size = sizeof (DWORD);
ret = RegQueryValueExW( hKey, L"Version", 0, &type, (LPBYTE)&version, &size );
if (ret != ERROR_SUCCESS || type != REG_DWORD)
DBGPRINT( "Warning: Couldn't query Version value or not a DWORD" );
size = sizeof (DWORD);
ret = RegQueryValueExW( hKey, L"DriverVersion", 0, &type,
(LPBYTE)&driverVersion, &size );
if (ret != ERROR_SUCCESS || type != REG_DWORD)
DBGPRINT( "Warning: Couldn't query DriverVersion value or not a DWORD" );
size = sizeof (DWORD);
ret = RegQueryValueExW( hKey, L"Flags", 0, &type, (LPBYTE)&flags, &size );
if (ret != ERROR_SUCCESS || type != REG_DWORD)
DBGPRINT( "Warning: Couldn't query Flags value or not a DWORD" );
/* close key */
RegCloseKey( hKey );
/* output data */
/* FIXME: NUL-terminate strings? */
wcsncpy( icd->driver_name, driver,
sizeof (icd->driver_name) / sizeof (icd->driver_name[0]) - 1 );
wcsncpy( icd->dll, dll,
sizeof (icd->dll) / sizeof (icd->dll[0]) );
icd->version = version;
icd->driver_version = driverVersion;
icd->flags = flags;
return ERROR_SUCCESS;
}
/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -