From ad61fd2df2c26bdfb41700af1853c92a0c3cbcec Mon Sep 17 00:00:00 2001 From: Kamil Hornicek Date: Sun, 19 Mar 2017 22:15:58 +0000 Subject: [PATCH] [OPENGL32] Disclaimer: This code is ReactOS specific and is the complete opposite of what Windows does (tm): - Add the option to override the default OpenGL driver by a custom driver or to force the use of the built-in software implementation. - This will allow some more flexibility when running games / apps that depend on OGL. - This code needs a special entry in the registry so opengl32 behaves as usual by default. svn path=/trunk/; revision=74207 --- reactos/dll/opengl/opengl32/icdload.c | 152 +++++++++++++++++++------- reactos/dll/opengl/opengl32/wgl.c | 4 +- 2 files changed, 113 insertions(+), 43 deletions(-) diff --git a/reactos/dll/opengl/opengl32/icdload.c b/reactos/dll/opengl/opengl32/icdload.c index 9068c6f8fb5..6b8a28b8e5f 100644 --- a/reactos/dll/opengl/opengl32/icdload.c +++ b/reactos/dll/opengl/opengl32/icdload.c @@ -11,16 +11,27 @@ WINE_DEFAULT_DEBUG_CHANNEL(opengl32); -struct Drv_Opengl_Info +typedef struct { DWORD Version; /*!< Driver interface version */ DWORD DriverVersion; /*!< Driver version */ WCHAR DriverName[256]; /*!< Driver name */ -}; +} Drv_Opengl_Info, *pDrv_Opengl_Info; + +typedef enum +{ + OGL_CD_NOT_QUERIED, + OGL_CD_NONE, + OGL_CD_ROSSWI, + OGL_CD_CUSTOM_ICD +} CUSTOM_DRIVER_STATE; static CRITICAL_SECTION icdload_cs = {NULL, -1, 0, 0, 0, 0}; static struct ICD_Data* ICD_Data_List = NULL; static const WCHAR OpenGLDrivers_Key[] = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\OpenGLDrivers"; +static const WCHAR CustomDrivers_Key[] = L"SOFTWARE\\ReactOS\\OpenGL"; +static Drv_Opengl_Info CustomDrvInfo; +static CUSTOM_DRIVER_STATE CustomDriverState = OGL_CD_NOT_QUERIED; static void APIENTRY wglSetCurrentValue(PVOID value) { @@ -47,42 +58,100 @@ struct ICD_Data* IntGetIcdData(HDC hdc) { int ret; DWORD dwInput, dwValueType, Version, DriverVersion, Flags; - struct Drv_Opengl_Info DrvInfo; + Drv_Opengl_Info DrvInfo; + pDrv_Opengl_Info pDrvInfo; struct ICD_Data* data; - HKEY OglKey, DrvKey; + HKEY OglKey, DrvKey, CustomKey; WCHAR DllName[MAX_PATH]; BOOL (WINAPI *DrvValidateVersion)(DWORD); void (WINAPI *DrvSetCallbackProcs)(int nProcs, PROC* pProcs); - - /* First, see if the driver supports this */ - dwInput = OPENGL_GETINFO; - ret = ExtEscape(hdc, - QUERYESCSUPPORT, - sizeof(DWORD), - (LPCSTR)&dwInput, - 0, - NULL); - - if(ret <= 0) + + /* The following code is ReactOS specific and allows us to easily load an arbitrary ICD: + * It checks HKCU\Software\ReactOS\OpenGL for a custom ICD and will always load it + * no matter what driver the DC is associated with. It can also force using the + * built-in Software Implementation*/ + if(CustomDriverState == OGL_CD_NOT_QUERIED) { - /* Driver doesn't support opengl */ - return NULL; + /* Only do this once so there's not any significant performance penalty */ + CustomDriverState = OGL_CD_NONE; + memset(&CustomDrvInfo, 0, sizeof(Drv_Opengl_Info)); + + ret = RegOpenKeyExW(HKEY_CURRENT_USER, CustomDrivers_Key, 0, KEY_READ, &CustomKey); + if(ret != ERROR_SUCCESS) + goto custom_end; + + dwInput = sizeof(CustomDrvInfo.DriverName); + ret = RegQueryValueExW(CustomKey, L"", 0, &dwValueType, (LPBYTE)CustomDrvInfo.DriverName, &dwInput); + RegCloseKey(CustomKey); + + if((ret != ERROR_SUCCESS) || (dwValueType != REG_SZ) || !wcslen(CustomDrvInfo.DriverName)) + goto custom_end; + + if(!_wcsicmp(CustomDrvInfo.DriverName, L"ReactOS Software Implementation")) + { + /* Always announce the fact that we're forcing ROSSWI */ + ERR("Forcing ReactOS Software Implementation\n"); + CustomDriverState = OGL_CD_ROSSWI; + return NULL; + } + + ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, OpenGLDrivers_Key, 0, KEY_READ, &OglKey); + if(ret != ERROR_SUCCESS) + goto custom_end; + + ret = RegOpenKeyExW(OglKey, CustomDrvInfo.DriverName, 0, KEY_READ, &OglKey); + if(ret != ERROR_SUCCESS) + goto custom_end; + + dwInput = sizeof(CustomDrvInfo.Version); + ret = RegQueryValueExW(OglKey, L"Version", 0, &dwValueType, (LPBYTE)&CustomDrvInfo.Version, &dwInput); + if((ret != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) + goto custom_end; + + dwInput = sizeof(DriverVersion); + ret = RegQueryValueExW(OglKey, L"DriverVersion", 0, &dwValueType, (LPBYTE)&CustomDrvInfo.DriverVersion, &dwInput); + CustomDriverState = OGL_CD_CUSTOM_ICD; + + /* Always announce the fact that we're overriding the default driver */ + ERR("Overriding the default OGL ICD with %S\n", CustomDrvInfo.DriverName); + +custom_end: + if(OglKey) + RegCloseKey(OglKey); + RegCloseKey(CustomKey); } - - /* Query for the ICD DLL name and version */ - dwInput = 0; - ret = ExtEscape(hdc, - OPENGL_GETINFO, - sizeof(DWORD), - (LPCSTR)&dwInput, - sizeof(DrvInfo), - (LPSTR)&DrvInfo); - - if(ret <= 0) + + /* If there's a custom ICD or ROSSWI was requested use it, otherwise proceed as usual */ + if(CustomDriverState == OGL_CD_CUSTOM_ICD) + { + pDrvInfo = &CustomDrvInfo; + } + else if(CustomDriverState == OGL_CD_ROSSWI) { - ERR("Driver claims to support OPENGL_GETINFO escape code, but doesn't.\n"); return NULL; } + else + { + /* First, see if the driver supports this */ + dwInput = OPENGL_GETINFO; + ret = ExtEscape(hdc, QUERYESCSUPPORT, sizeof(DWORD), (LPCSTR)&dwInput, 0, NULL); + + /* Driver doesn't support opengl */ + if(ret <= 0) + return NULL; + + /* Query for the ICD DLL name and version */ + dwInput = 0; + ret = ExtEscape(hdc, OPENGL_GETINFO, sizeof(DWORD), (LPCSTR)&dwInput, sizeof(DrvInfo), (LPSTR)&DrvInfo); + + if(ret <= 0) + { + ERR("Driver claims to support OPENGL_GETINFO escape code, but doesn't.\n"); + return NULL; + } + + pDrvInfo = &DrvInfo; + } /* Protect the list while we are loading*/ EnterCriticalSection(&icdload_cs); @@ -91,7 +160,7 @@ struct ICD_Data* IntGetIcdData(HDC hdc) data = ICD_Data_List; while(data) { - if(!_wcsicmp(data->DriverName, DrvInfo.DriverName)) + if(!_wcsicmp(data->DriverName, pDrvInfo->DriverName)) { /* Found it */ TRACE("Found already loaded %p.\n", data); @@ -108,16 +177,16 @@ struct ICD_Data* IntGetIcdData(HDC hdc) ERR("Failed to open the OpenGLDrivers key.\n"); goto end; } - ret = RegOpenKeyExW(OglKey, DrvInfo.DriverName, 0, KEY_READ, &DrvKey); + ret = RegOpenKeyExW(OglKey, pDrvInfo->DriverName, 0, KEY_READ, &DrvKey); if(ret != ERROR_SUCCESS) { /* Some driver installer just provide the DLL name, like the Matrox G400 */ - TRACE("No driver subkey for %S, trying to get DLL name directly.\n", DrvInfo.DriverName); + TRACE("No driver subkey for %S, trying to get DLL name directly.\n", pDrvInfo->DriverName); dwInput = sizeof(DllName); - ret = RegQueryValueExW(OglKey, DrvInfo.DriverName, 0, &dwValueType, (LPBYTE)DllName, &dwInput); + ret = RegQueryValueExW(OglKey, pDrvInfo->DriverName, 0, &dwValueType, (LPBYTE)DllName, &dwInput); if((ret != ERROR_SUCCESS) || (dwValueType != REG_SZ)) { - ERR("Unable to get ICD DLL name!.\n"); + ERR("Unable to get ICD DLL name!\n"); RegCloseKey(OglKey); goto end; } @@ -127,7 +196,7 @@ struct ICD_Data* IntGetIcdData(HDC hdc) else { /* The driver have a subkey for the ICD */ - TRACE("Querying details from registry for %S.\n", DrvInfo.DriverName); + TRACE("Querying details from registry for %S.\n", pDrvInfo->DriverName); dwInput = sizeof(DllName); ret = RegQueryValueExW(DrvKey, L"Dll", 0, &dwValueType, (LPBYTE)DllName, &dwInput); if((ret != ERROR_SUCCESS) || (dwValueType != REG_SZ)) @@ -144,9 +213,9 @@ struct ICD_Data* IntGetIcdData(HDC hdc) { WARN("No version in driver subkey\n"); } - else if(Version != DrvInfo.Version) + else if(Version != pDrvInfo->Version) { - ERR("Version mismatch between registry (%lu) and display driver (%lu).\n", Version, DrvInfo.Version); + ERR("Version mismatch between registry (%lu) and display driver (%lu).\n", Version, pDrvInfo->Version); RegCloseKey(DrvKey); RegCloseKey(OglKey); goto end; @@ -158,9 +227,9 @@ struct ICD_Data* IntGetIcdData(HDC hdc) { WARN("No driver version in driver subkey\n"); } - else if(DriverVersion != DrvInfo.DriverVersion) + else if(DriverVersion != pDrvInfo->DriverVersion) { - ERR("Driver version mismatch between registry (%lu) and display driver (%lu).\n", DriverVersion, DrvInfo.DriverVersion); + ERR("Driver version mismatch between registry (%lu) and display driver (%lu).\n", DriverVersion, pDrvInfo->DriverVersion); RegCloseKey(DrvKey); RegCloseKey(OglKey); goto end; @@ -206,7 +275,7 @@ struct ICD_Data* IntGetIcdData(HDC hdc) DrvValidateVersion = (void*)GetProcAddress(data->hModule, "DrvValidateVersion"); if(DrvValidateVersion) { - if(!DrvValidateVersion(DrvInfo.DriverVersion)) + if(!DrvValidateVersion(pDrvInfo->DriverVersion)) { ERR("DrvValidateVersion failed!.\n"); goto fail; @@ -262,13 +331,14 @@ struct ICD_Data* IntGetIcdData(HDC hdc) } /* Copy the DriverName */ - wcscpy(data->DriverName, DrvInfo.DriverName); + wcscpy(data->DriverName, pDrvInfo->DriverName); /* Push the list */ data->next = ICD_Data_List; ICD_Data_List = data; TRACE("Returning %p.\n", data); + TRACE("ICD driver %S (%S) successfully loaded.\n", pDrvInfo->DriverName, DllName); end: /* Unlock and return */ diff --git a/reactos/dll/opengl/opengl32/wgl.c b/reactos/dll/opengl/opengl32/wgl.c index 701cc19bbb1..82213d88008 100644 --- a/reactos/dll/opengl/opengl32/wgl.c +++ b/reactos/dll/opengl/opengl32/wgl.c @@ -79,7 +79,7 @@ get_dc_data(HDC hdc) data->nb_icd_formats = data->icd_data->DrvDescribePixelFormat(hdc, 0, 0, NULL); else data->nb_icd_formats = 0; - TRACE("ICD %S has %u formats for HDC %x.\n", data->icd_data->DriverName, data->nb_icd_formats, hdc); + TRACE("ICD %S has %u formats for HDC %x.\n", data->icd_data ? data->icd_data->DriverName : NULL, data->nb_icd_formats, hdc); data->nb_sw_formats = sw_DescribePixelFormat(hdc, 0, 0, NULL); data->next = dc_data_list; dc_data_list = data; @@ -927,6 +927,6 @@ IntDeleteAllContexts(void) { context = CONTAINING_RECORD(Entry, struct wgl_context, ListEntry); wglDeleteContext((HGLRC)context); - Entry = ContextListHead.Flink; + Entry = Entry->Flink; } } -- 2.17.1