diff --git a/reactos/dll/opengl/opengl32/dllmain.c b/reactos/dll/opengl/opengl32/dllmain.c index 9d8f9dfe5a3..9d4ced2114c 100644 --- a/reactos/dll/opengl/opengl32/dllmain.c +++ b/reactos/dll/opengl/opengl32/dllmain.c @@ -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 +} diff --git a/reactos/dll/opengl/opengl32/icdload.c b/reactos/dll/opengl/opengl32/icdload.c index f4029cfe651..9068c6f8fb5 100644 --- a/reactos/dll/opengl/opengl32/icdload.c +++ b/reactos/dll/opengl/opengl32/icdload.c @@ -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); + } +} diff --git a/reactos/dll/opengl/opengl32/opengl32.h b/reactos/dll/opengl/opengl32/opengl32.h index ea2ea2c31ec..d26f1071616 100644 --- a/reactos/dll/opengl/opengl32/opengl32.h +++ b/reactos/dll/opengl/opengl32/opengl32.h @@ -21,11 +21,56 @@ #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; diff --git a/reactos/dll/opengl/opengl32/wgl.c b/reactos/dll/opengl/opengl32/wgl.c index 8da98b9d350..701cc19bbb1 100644 --- a/reactos/dll/opengl/opengl32/wgl.c +++ b/reactos/dll/opengl/opengl32/wgl.c @@ -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; + } +}