⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 opengl32.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 2 页
字号:
	}

	/* 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 + -