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/dllmai…
==============================================================================
--- 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/icdloa…
==============================================================================
--- 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/opengl…
==============================================================================
--- 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?…
==============================================================================
--- 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;
+ }
+}