[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!)

svn path=/trunk/; revision=63747
This commit is contained in:
Jérôme Gardou 2014-07-28 13:03:10 +00:00
parent 84fa6f66f3
commit b6f852e3a4
4 changed files with 133 additions and 17 deletions

View 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;
}
}

View 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;
}
}
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);
}
}

View file

@ -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;

View 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;
}
}