Author: jgardou Date: Mon Jul 28 13:03:10 2014 New Revision: 63747
URL: http://svn.reactos.org/svn/reactos?rev=63747&view=rev Log: [OPENGL32] - Free resources when unloading the DLL - avoid potential crash in wglDescribePixelFormat - Prefer HW accelerated pixel formats in wglChoosePixelFormat - Try forwarding ICD functions to win32k when relevant (untested!)
Modified: trunk/reactos/dll/opengl/opengl32/dllmain.c trunk/reactos/dll/opengl/opengl32/icdload.c trunk/reactos/dll/opengl/opengl32/opengl32.h trunk/reactos/dll/opengl/opengl32/wgl.c
Modified: trunk/reactos/dll/opengl/opengl32/dllmain.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/opengl/opengl32/dllmain... ============================================================================== --- trunk/reactos/dll/opengl/opengl32/dllmain.c [iso-8859-1] (original) +++ trunk/reactos/dll/opengl/opengl32/dllmain.c [iso-8859-1] Mon Jul 28 13:03:10 2014 @@ -19,16 +19,15 @@ #endif switch ( Reason ) { - /* The DLL is loading due to process - * initialization or a call to LoadLibrary. - */ case DLL_PROCESS_ATTACH: #ifdef OPENGL32_USE_TLS OglTlsIndex = TlsAlloc(); if(OglTlsIndex == TLS_OUT_OF_INDEXES) return FALSE; #endif - /* Fall through */ + /* Initialize Context list */ + InitializeListHead(&ContextListHead); + /* no break */ case DLL_THREAD_ATTACH: #ifdef OPENGL32_USE_TLS ThreadData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ThreadData)); @@ -45,28 +44,36 @@ break;
case DLL_THREAD_DETACH: + /* Set NULL context for this thread */ + wglMakeCurrent(NULL, NULL); /* Clean up */ #ifdef OPENGL32_USE_TLS ThreadData = TlsGetValue(OglTlsIndex); if(ThreadData) HeapFree(GetProcessHeap(), 0, ThreadData); #else - NtCurrentTeb->glTable = NULL; + NtCurrentTeb()->glTable = NULL; #endif // defined(OPENGL32_USE_TLS) - break; - + break; case DLL_PROCESS_DETACH: /* Clean up */ + if (!Reserved) + { + /* The process is not shutting down: release everything */ + wglMakeCurrent(NULL, NULL); + IntDeleteAllContexts(); + IntDeleteAllICDs(); #ifdef OPENGL32_USE_TLS - ThreadData = TlsGetValue(OglTlsIndex); - if(ThreadData) - HeapFree(GetProcessHeap(), 0, ThreadData); + ThreadData = TlsGetValue(OglTlsIndex); + if(ThreadData) + HeapFree(GetProcessHeap(), 0, ThreadData); +#endif + } +#ifdef OPENGL32_USE_TLS TlsFree(OglTlsIndex); -#else - NtCurrentTeb->glTable = NULL; -#endif // defined(OPENGL32_USE_TLS) +#endif break; }
return TRUE; -} +}
Modified: trunk/reactos/dll/opengl/opengl32/icdload.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/opengl/opengl32/icdload... ============================================================================== --- trunk/reactos/dll/opengl/opengl32/icdload.c [iso-8859-1] (original) +++ trunk/reactos/dll/opengl/opengl32/icdload.c [iso-8859-1] Mon Jul 28 13:03:10 2014 @@ -36,6 +36,11 @@ { return context->dhglrc; } + +/* GDI entry points (win32k) */ +extern INT APIENTRY GdiDescribePixelFormat(HDC hdc, INT ipfd, UINT cjpfd, PPIXELFORMATDESCRIPTOR ppfd); +extern BOOL APIENTRY GdiSetPixelFormat(HDC hdc, INT ipfd); +extern BOOL APIENTRY GdiSwapBuffers(HDC hdc);
/* Retrieves the ICD data (driver version + relevant DLL entry points) for a device context */ struct ICD_Data* IntGetIcdData(HDC hdc) @@ -245,6 +250,17 @@ DRV_LOAD(DrvSwapLayerBuffers); #undef DRV_LOAD
+ /* Let's see if GDI should handle this instead of the ICD DLL */ + // FIXME: maybe there is a better way + if (GdiDescribePixelFormat(hdc, 0, 0, NULL) != 0) + { + /* GDI knows what to do with that. Override */ + TRACE("Forwarding WGL calls to win32k!\n"); + data->DrvDescribePixelFormat = GdiDescribePixelFormat; + data->DrvSetPixelFormat = GdiSetPixelFormat; + data->DrvSwapBuffers = GdiSwapBuffers; + } + /* Copy the DriverName */ wcscpy(data->DriverName, DrvInfo.DriverName);
@@ -264,4 +280,20 @@ FreeLibrary(data->hModule); HeapFree(GetProcessHeap(), 0, data); return NULL; -} +} + +void IntDeleteAllICDs(void) +{ + struct ICD_Data* data; + + EnterCriticalSection(&icdload_cs); + + while (ICD_Data_List != NULL) + { + data = ICD_Data_List; + ICD_Data_List = data->next; + + FreeLibrary(data->hModule); + HeapFree(GetProcessHeap(), 0, data); + } +}
Modified: trunk/reactos/dll/opengl/opengl32/opengl32.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/opengl/opengl32/opengl3... ============================================================================== --- trunk/reactos/dll/opengl/opengl32/opengl32.h [iso-8859-1] (original) +++ trunk/reactos/dll/opengl/opengl32/opengl32.h [iso-8859-1] Mon Jul 28 13:03:10 2014 @@ -21,10 +21,55 @@
#include "icd.h"
+/* *$%$£^§! headers inclusion */ +static __inline +BOOLEAN +RemoveEntryList( + _In_ PLIST_ENTRY Entry) +{ + PLIST_ENTRY OldFlink; + PLIST_ENTRY OldBlink; + + OldFlink = Entry->Flink; + OldBlink = Entry->Blink; + OldFlink->Blink = OldBlink; + OldBlink->Flink = OldFlink; + return (OldFlink == OldBlink); +} + +static __inline +VOID +InsertTailList( + _In_ PLIST_ENTRY ListHead, + _In_ PLIST_ENTRY Entry +) +{ + PLIST_ENTRY OldBlink; + OldBlink = ListHead->Blink; + Entry->Flink = ListHead; + Entry->Blink = OldBlink; + OldBlink->Flink = Entry; + ListHead->Blink = Entry; +} + + +static __inline +VOID +InitializeListHead( + _Inout_ PLIST_ENTRY ListHead +) +{ + ListHead->Flink = ListHead->Blink = ListHead; +} + +extern LIST_ENTRY ContextListHead; + struct wgl_context { DWORD magic; volatile LONG lock; + + LIST_ENTRY ListEntry;
DHGLRC dhglrc; struct ICD_Data* icd_data; @@ -58,6 +103,10 @@ /* Linked list */ struct wgl_dc_data* next; }; + +/* Clean up functions */ +void IntDeleteAllContexts(void); +void IntDeleteAllICDs(void);
#ifdef OPENGL32_USE_TLS extern DWORD OglTlsIndex;
Modified: trunk/reactos/dll/opengl/opengl32/wgl.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/opengl/opengl32/wgl.c?r... ============================================================================== --- trunk/reactos/dll/opengl/opengl32/wgl.c [iso-8859-1] (original) +++ trunk/reactos/dll/opengl/opengl32/wgl.c [iso-8859-1] Mon Jul 28 13:03:10 2014 @@ -13,6 +13,8 @@
static CRITICAL_SECTION dc_data_cs = {NULL, -1, 0, 0, 0, 0}; static struct wgl_dc_data* dc_data_list = NULL; + +LIST_ENTRY ContextListHead;
/* FIXME: suboptimal */ static @@ -139,7 +141,11 @@ /* Query ICD if needed */ if(format <= dc_data->nb_icd_formats) { - if(!dc_data->icd_data->DrvDescribePixelFormat(hdc, format, size, descr)) + struct ICD_Data* icd_data = dc_data->icd_data; + /* SetPixelFormat may have NULLified this */ + if (!icd_data) + icd_data = IntGetIcdData(hdc); + if(!icd_data->DrvDescribePixelFormat(hdc, format, size, descr)) { ret = 0; } @@ -174,7 +180,7 @@ if (!count) return 0;
best_format = 0; - best.dwFlags = 0; + best.dwFlags = PFD_GENERIC_FORMAT; best.cAlphaBits = -1; best.cColorBits = -1; best.cDepthBits = -1; @@ -329,6 +335,9 @@ continue;
found: + /* Prefer HW accelerated formats */ + if ((format.dwFlags & PFD_GENERIC_FORMAT) && !(best.dwFlags & PFD_GENERIC_FORMAT)) + continue; best_format = i; best = format; bestDBuffer = format.dwFlags & PFD_DOUBLEBUFFER; @@ -422,6 +431,9 @@ context->pixelformat = dc_data->pixelformat; context->thread_id = 0;
+ /* Insert into the list */ + InsertTailList(&ContextListHead, &context->ListEntry); + context->magic = 'GLRC'; TRACE("Success!\n"); return (HGLRC)context; @@ -525,6 +537,7 @@ sw_DeleteContext(context->dhglrc);
context->magic = 0; + RemoveEntryList(&context->ListEntry); HeapFree(GetProcessHeap(), 0, context);
return TRUE; @@ -902,3 +915,18 @@ { return 0; } + +/* Clean up on DLL unload */ +void +IntDeleteAllContexts(void) +{ + struct wgl_context* context; + LIST_ENTRY* Entry = ContextListHead.Flink; + + while (Entry != &ContextListHead) + { + context = CONTAINING_RECORD(Entry, struct wgl_context, ListEntry); + wglDeleteContext((HGLRC)context); + Entry = ContextListHead.Flink; + } +}