[OPENGL32]
authorKamil Hornicek <kamil.hornicek@reactos.org>
Sun, 19 Mar 2017 22:15:58 +0000 (22:15 +0000)
committerKamil Hornicek <kamil.hornicek@reactos.org>
Sun, 19 Mar 2017 22:15:58 +0000 (22:15 +0000)
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
reactos/dll/opengl/opengl32/wgl.c

index 9068c6f..6b8a28b 100644 (file)
 
 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 */
index 701cc19..82213d8 100644 (file)
@@ -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;
     }
 }