[OPENGL32]
authorJérôme Gardou <jerome.gardou@reactos.org>
Mon, 28 Jul 2014 13:03:10 +0000 (13:03 +0000)
committerJérôme Gardou <jerome.gardou@reactos.org>
Mon, 28 Jul 2014 13:03:10 +0000 (13:03 +0000)
 - 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!)

svn path=/trunk/; revision=63747

reactos/dll/opengl/opengl32/dllmain.c
reactos/dll/opengl/opengl32/icdload.c
reactos/dll/opengl/opengl32/opengl32.h
reactos/dll/opengl/opengl32/wgl.c

index 9d8f9df..9d4ced2 100644 (file)
@@ -19,16 +19,15 @@ DllMain(HINSTANCE hInstance, DWORD Reason, LPVOID Reserved)
 #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 @@ DllMain(HINSTANCE hInstance, DWORD Reason, LPVOID Reserved)
             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);
+#endif
+            }
 #ifdef OPENGL32_USE_TLS
-            ThreadData = TlsGetValue(OglTlsIndex);
-            if(ThreadData)
-                HeapFree(GetProcessHeap(), 0, ThreadData);
             TlsFree(OglTlsIndex);
-#else
-            NtCurrentTeb->glTable = NULL;
-#endif // defined(OPENGL32_USE_TLS)
+#endif
             break;
     }
 
     return TRUE;
-}
\ No newline at end of file
+}
index f4029cf..9068c6f 100644 (file)
@@ -37,6 +37,11 @@ static DHGLRC wglGetDHGLRC(struct wgl_context* context)
     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 @@ struct ICD_Data* IntGetIcdData(HDC hdc)
     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 @@ fail:
     FreeLibrary(data->hModule);
     HeapFree(GetProcessHeap(), 0, data);
     return NULL;
-}
\ No newline at end of file
+}
+
+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);
+    }
+}
index ea2ea2c..d26f107 100644 (file)
 
 #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;
     INT pixelformat;
@@ -59,6 +104,10 @@ struct wgl_dc_data
     struct wgl_dc_data* next;
 };
 
+/* Clean up functions */
+void IntDeleteAllContexts(void);
+void IntDeleteAllICDs(void);
+
 #ifdef OPENGL32_USE_TLS
 extern DWORD OglTlsIndex;
 
index 8da98b9..701cc19 100644 (file)
@@ -14,6 +14,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(wgl);
 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
 struct wgl_dc_data*
@@ -139,7 +141,11 @@ INT WINAPI wglDescribePixelFormat(HDC hdc, INT format, UINT size, PIXELFORMATDES
     /* 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 @@ INT WINAPI wglChoosePixelFormat(HDC hdc, const PIXELFORMATDESCRIPTOR* ppfd)
     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 @@ INT WINAPI wglChoosePixelFormat(HDC hdc, const PIXELFORMATDESCRIPTOR* ppfd)
         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 @@ HGLRC WINAPI wglCreateContext(HDC hdc)
     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 @@ BOOL WINAPI wglDeleteContext(HGLRC hglrc)
         sw_DeleteContext(context->dhglrc);
     
     context->magic = 0;
+    RemoveEntryList(&context->ListEntry);
     HeapFree(GetProcessHeap(), 0, context);
     
     return TRUE;
@@ -902,3 +915,18 @@ DWORD WINAPI wglSwapMultipleBuffers(UINT count, CONST WGLSWAP * toSwap)
 {
     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;
+    }
+}