opengl32: Make the WGL driver context-specific.

This commit is contained in:
Alexandre Julliard 2012-06-29 15:53:37 +02:00
parent 676194383c
commit 83be88953b
4 changed files with 55 additions and 39 deletions

View File

@ -686,7 +686,7 @@ static void nulldrv_wglDeleteContext( struct wgl_context *context )
{ {
} }
static HDC nulldrv_wglGetCurrentDC(void) static HDC nulldrv_wglGetCurrentDC( struct wgl_context *context )
{ {
return 0; return 0;
} }

View File

@ -54,8 +54,6 @@ static struct
void (WINAPI *p_wglGetIntegerv)(GLenum pname, GLint* params); void (WINAPI *p_wglGetIntegerv)(GLenum pname, GLint* params);
} wine_wgl; } wine_wgl;
static const struct wgl_funcs *wgl_driver;
#ifdef SONAME_LIBGLU #ifdef SONAME_LIBGLU
#define MAKE_FUNCPTR(f) static typeof(f) * p##f; #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
MAKE_FUNCPTR(gluNewTess) MAKE_FUNCPTR(gluNewTess)
@ -85,9 +83,10 @@ extern BOOL WINAPI GdiSwapBuffers( HDC hdc );
struct wgl_handle struct wgl_handle
{ {
UINT handle; UINT handle;
DWORD tid; DWORD tid;
struct wgl_context *context; struct wgl_context * context;
const struct wgl_funcs *funcs;
}; };
static struct wgl_handle wgl_handles[MAX_WGL_HANDLES]; static struct wgl_handle wgl_handles[MAX_WGL_HANDLES];
@ -103,6 +102,11 @@ static CRITICAL_SECTION_DEBUG critsect_debug =
}; };
static CRITICAL_SECTION wgl_section = { &critsect_debug, -1, 0, 0, 0, 0 }; static CRITICAL_SECTION wgl_section = { &critsect_debug, -1, 0, 0, 0, 0 };
static inline const struct wgl_funcs *get_dc_funcs( HDC hdc )
{
return __wine_get_wgl_driver( hdc, WINE_GDI_DRIVER_VERSION );
}
static inline HGLRC next_handle( struct wgl_handle *ptr ) static inline HGLRC next_handle( struct wgl_handle *ptr )
{ {
WORD generation = HIWORD( ptr->handle ) + 1; WORD generation = HIWORD( ptr->handle ) + 1;
@ -136,7 +140,7 @@ static void release_handle_ptr( struct wgl_handle *ptr )
if (ptr) LeaveCriticalSection( &wgl_section ); if (ptr) LeaveCriticalSection( &wgl_section );
} }
static HGLRC alloc_handle( struct wgl_context *context ) static HGLRC alloc_handle( struct wgl_context *context, const struct wgl_funcs *funcs )
{ {
HGLRC handle = 0; HGLRC handle = 0;
struct wgl_handle *ptr = NULL; struct wgl_handle *ptr = NULL;
@ -150,6 +154,7 @@ static HGLRC alloc_handle( struct wgl_context *context )
if (ptr) if (ptr)
{ {
ptr->context = context; ptr->context = context;
ptr->funcs = funcs;
handle = next_handle( ptr ); handle = next_handle( ptr );
} }
else SetLastError( ERROR_NOT_ENOUGH_MEMORY ); else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
@ -161,6 +166,7 @@ static void free_handle_ptr( struct wgl_handle *ptr )
{ {
ptr->handle &= ~0xffff; ptr->handle &= ~0xffff;
ptr->context = (struct wgl_context *)next_free; ptr->context = (struct wgl_context *)next_free;
ptr->funcs = NULL;
next_free = ptr; next_free = ptr;
LeaveCriticalSection( &wgl_section ); LeaveCriticalSection( &wgl_section );
} }
@ -184,8 +190,10 @@ BOOL WINAPI wglCopyContext(HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask)
if (!(src = get_handle_ptr( hglrcSrc ))) return FALSE; if (!(src = get_handle_ptr( hglrcSrc ))) return FALSE;
if ((dst = get_handle_ptr( hglrcDst ))) if ((dst = get_handle_ptr( hglrcDst )))
ret = wgl_driver->p_wglCopyContext( src->context, dst->context, mask ); {
if (src->funcs != dst->funcs) SetLastError( ERROR_INVALID_HANDLE );
else ret = src->funcs->p_wglCopyContext( src->context, dst->context, mask );
}
release_handle_ptr( dst ); release_handle_ptr( dst );
release_handle_ptr( src ); release_handle_ptr( src );
return ret; return ret;
@ -207,7 +215,7 @@ BOOL WINAPI wglDeleteContext(HGLRC hglrc)
return FALSE; return FALSE;
} }
if (hglrc == NtCurrentTeb()->glCurrentRC) wglMakeCurrent( 0, 0 ); if (hglrc == NtCurrentTeb()->glCurrentRC) wglMakeCurrent( 0, 0 );
wgl_driver->p_wglDeleteContext( ptr->context ); ptr->funcs->p_wglDeleteContext( ptr->context );
free_handle_ptr( ptr ); free_handle_ptr( ptr );
return TRUE; return TRUE;
} }
@ -225,7 +233,7 @@ BOOL WINAPI wglMakeCurrent(HDC hdc, HGLRC hglrc)
if (!(ptr = get_handle_ptr( hglrc ))) return FALSE; if (!(ptr = get_handle_ptr( hglrc ))) return FALSE;
if (!ptr->tid || ptr->tid == GetCurrentThreadId()) if (!ptr->tid || ptr->tid == GetCurrentThreadId())
{ {
ret = wgl_driver->p_wglMakeCurrent( hdc, ptr->context ); ret = ptr->funcs->p_wglMakeCurrent( hdc, ptr->context );
if (ret) if (ret)
{ {
if (prev) prev->tid = 0; if (prev) prev->tid = 0;
@ -242,7 +250,7 @@ BOOL WINAPI wglMakeCurrent(HDC hdc, HGLRC hglrc)
} }
else if (prev) else if (prev)
{ {
if (!wgl_driver->p_wglMakeCurrent( 0, NULL )) return FALSE; if (!prev->funcs->p_wglMakeCurrent( 0, NULL )) return FALSE;
prev->tid = 0; prev->tid = 0;
NtCurrentTeb()->glCurrentRC = 0; NtCurrentTeb()->glCurrentRC = 0;
} }
@ -262,13 +270,15 @@ static HGLRC WINAPI wglCreateContextAttribsARB( HDC hdc, HGLRC share, const int
HGLRC ret = 0; HGLRC ret = 0;
struct wgl_context *context; struct wgl_context *context;
struct wgl_handle *share_ptr = NULL; struct wgl_handle *share_ptr = NULL;
const struct wgl_funcs *funcs = get_dc_funcs( hdc );
if (!funcs) return 0;
if (share && !(share_ptr = get_handle_ptr( share ))) return 0; if (share && !(share_ptr = get_handle_ptr( share ))) return 0;
if ((context = wgl_driver->p_wglCreateContextAttribsARB( hdc, share_ptr ? share_ptr->context : NULL, if ((context = funcs->p_wglCreateContextAttribsARB( hdc, share_ptr ? share_ptr->context : NULL,
attribs ))) attribs )))
{ {
ret = alloc_handle( context ); ret = alloc_handle( context, funcs );
if (!ret) wgl_driver->p_wglDeleteContext( context ); if (!ret) funcs->p_wglDeleteContext( context );
} }
release_handle_ptr( share_ptr ); release_handle_ptr( share_ptr );
return ret; return ret;
@ -288,7 +298,7 @@ static BOOL WINAPI wglMakeContextCurrentARB( HDC draw_hdc, HDC read_hdc, HGLRC h
if (!(ptr = get_handle_ptr( hglrc ))) return FALSE; if (!(ptr = get_handle_ptr( hglrc ))) return FALSE;
if (!ptr->tid || ptr->tid == GetCurrentThreadId()) if (!ptr->tid || ptr->tid == GetCurrentThreadId())
{ {
ret = wgl_driver->p_wglMakeContextCurrentARB( draw_hdc, read_hdc, ptr->context ); ret = ptr->funcs->p_wglMakeContextCurrentARB( draw_hdc, read_hdc, ptr->context );
if (ret) if (ret)
{ {
if (prev) prev->tid = 0; if (prev) prev->tid = 0;
@ -305,7 +315,7 @@ static BOOL WINAPI wglMakeContextCurrentARB( HDC draw_hdc, HDC read_hdc, HGLRC h
} }
else if (prev) else if (prev)
{ {
if (!wgl_driver->p_wglMakeCurrent( 0, NULL )) return FALSE; if (!prev->funcs->p_wglMakeCurrent( 0, NULL )) return FALSE;
prev->tid = 0; prev->tid = 0;
NtCurrentTeb()->glCurrentRC = 0; NtCurrentTeb()->glCurrentRC = 0;
} }
@ -322,8 +332,10 @@ BOOL WINAPI wglShareLists(HGLRC hglrcSrc, HGLRC hglrcDst)
if (!(src = get_handle_ptr( hglrcSrc ))) return FALSE; if (!(src = get_handle_ptr( hglrcSrc ))) return FALSE;
if ((dst = get_handle_ptr( hglrcDst ))) if ((dst = get_handle_ptr( hglrcDst )))
ret = wgl_driver->p_wglShareLists( src->context, dst->context ); {
if (src->funcs != dst->funcs) SetLastError( ERROR_INVALID_HANDLE );
else ret = src->funcs->p_wglShareLists( src->context, dst->context );
}
release_handle_ptr( dst ); release_handle_ptr( dst );
release_handle_ptr( src ); release_handle_ptr( src );
return ret; return ret;
@ -334,7 +346,9 @@ BOOL WINAPI wglShareLists(HGLRC hglrcSrc, HGLRC hglrcDst)
*/ */
HDC WINAPI wglGetCurrentDC(void) HDC WINAPI wglGetCurrentDC(void)
{ {
return wgl_driver->p_wglGetCurrentDC(); struct wgl_handle *context = get_current_handle_ptr();
if (!context) return 0;
return context->funcs->p_wglGetCurrentDC( context->context );
} }
/*********************************************************************** /***********************************************************************
@ -343,11 +357,13 @@ HDC WINAPI wglGetCurrentDC(void)
HGLRC WINAPI wglCreateContext(HDC hdc) HGLRC WINAPI wglCreateContext(HDC hdc)
{ {
HGLRC ret = 0; HGLRC ret = 0;
struct wgl_context *context = wgl_driver->p_wglCreateContext( hdc ); struct wgl_context *context;
const struct wgl_funcs *funcs = get_dc_funcs( hdc );
if (!context) return 0; if (!funcs) return 0;
ret = alloc_handle( context ); if (!(context = funcs->p_wglCreateContext( hdc ))) return 0;
if (!ret) wgl_driver->p_wglDeleteContext( context ); ret = alloc_handle( context, funcs );
if (!ret) funcs->p_wglDeleteContext( context );
return ret; return ret;
} }
@ -536,7 +552,9 @@ INT WINAPI wglDescribePixelFormat(HDC hdc, INT iPixelFormat, UINT nBytes,
*/ */
INT WINAPI wglGetPixelFormat(HDC hdc) INT WINAPI wglGetPixelFormat(HDC hdc)
{ {
return wgl_driver->p_GetPixelFormat( hdc ); const struct wgl_funcs *funcs = get_dc_funcs( hdc );
if (!funcs) return 0;
return funcs->p_GetPixelFormat( hdc );
} }
/*********************************************************************** /***********************************************************************
@ -659,6 +677,7 @@ PROC WINAPI wglGetProcAddress(LPCSTR lpszProc) {
void *local_func; void *local_func;
OpenGL_extension ext; OpenGL_extension ext;
const OpenGL_extension *ext_ret; const OpenGL_extension *ext_ret;
struct wgl_handle *context = get_current_handle_ptr();
TRACE("(%s)\n", lpszProc); TRACE("(%s)\n", lpszProc);
@ -668,7 +687,7 @@ PROC WINAPI wglGetProcAddress(LPCSTR lpszProc) {
/* Without an active context opengl32 doesn't know to what /* Without an active context opengl32 doesn't know to what
* driver it has to dispatch wglGetProcAddress. * driver it has to dispatch wglGetProcAddress.
*/ */
if (wglGetCurrentContext() == NULL) if (!context)
{ {
WARN("No active WGL context found\n"); WARN("No active WGL context found\n");
return NULL; return NULL;
@ -684,7 +703,7 @@ PROC WINAPI wglGetProcAddress(LPCSTR lpszProc) {
/* If the function name starts with a 'w', it is a WGL extension */ /* If the function name starts with a 'w', it is a WGL extension */
if(lpszProc[0] == 'w') if(lpszProc[0] == 'w')
{ {
local_func = wgl_driver->p_wglGetProcAddress( lpszProc ); local_func = context->funcs->p_wglGetProcAddress( lpszProc );
if (local_func == (void *)1) /* special function that needs a wrapper */ if (local_func == (void *)1) /* special function that needs a wrapper */
{ {
ext_ret = bsearch( &ext, wgl_extensions, sizeof(wgl_extensions)/sizeof(wgl_extensions[0]), ext_ret = bsearch( &ext, wgl_extensions, sizeof(wgl_extensions)/sizeof(wgl_extensions[0]),
@ -707,7 +726,7 @@ PROC WINAPI wglGetProcAddress(LPCSTR lpszProc) {
WARN("Extension '%s' required by function '%s' not supported!\n", ext_ret->extension, lpszProc); WARN("Extension '%s' required by function '%s' not supported!\n", ext_ret->extension, lpszProc);
} }
local_func = wgl_driver->p_wglGetProcAddress(ext_ret->name); local_func = context->funcs->p_wglGetProcAddress( ext_ret->name );
/* After that, look at the extensions defined in the Linux OpenGL library */ /* After that, look at the extensions defined in the Linux OpenGL library */
if (local_func == NULL) { if (local_func == NULL) {
@ -1290,14 +1309,14 @@ BOOL WINAPI DECLSPEC_HOTPATCH wglSwapBuffers( HDC hdc )
static BOOL process_attach(void) static BOOL process_attach(void)
{ {
HDC hdc = GetDC( 0 ); HDC hdc = GetDC( 0 );
const struct wgl_funcs *funcs = get_dc_funcs( hdc );
wgl_driver = __wine_get_wgl_driver( hdc, WINE_GDI_DRIVER_VERSION );
ReleaseDC( 0, hdc ); ReleaseDC( 0, hdc );
/* internal WGL functions */ /* internal WGL functions */
wine_wgl.p_wglFinish = (void *)wgl_driver->p_wglGetProcAddress("wglFinish"); wine_wgl.p_wglFinish = (void *)funcs->p_wglGetProcAddress("wglFinish");
wine_wgl.p_wglFlush = (void *)wgl_driver->p_wglGetProcAddress("wglFlush"); wine_wgl.p_wglFlush = (void *)funcs->p_wglGetProcAddress("wglFlush");
wine_wgl.p_wglGetIntegerv = (void *)wgl_driver->p_wglGetProcAddress("wglGetIntegerv"); wine_wgl.p_wglGetIntegerv = (void *)funcs->p_wglGetProcAddress("wglGetIntegerv");
return TRUE; return TRUE;
} }

View File

@ -1728,11 +1728,8 @@ static BOOL glxdrv_wglShareLists(struct wgl_context *org, struct wgl_context *de
/*********************************************************************** /***********************************************************************
* glxdrv_wglGetCurrentDC * glxdrv_wglGetCurrentDC
*/ */
static HDC glxdrv_wglGetCurrentDC(void) static HDC glxdrv_wglGetCurrentDC( struct wgl_context *ctx )
{ {
struct wgl_context *ctx = NtCurrentTeb()->glContext;
if (!ctx) return NULL;
TRACE("hdc %p\n", ctx->hdc); TRACE("hdc %p\n", ctx->hdc);
return ctx->hdc; return ctx->hdc;
} }

View File

@ -198,7 +198,7 @@ struct gdi_dc_funcs
}; };
/* increment this when you change the DC function table */ /* increment this when you change the DC function table */
#define WINE_GDI_DRIVER_VERSION 40 #define WINE_GDI_DRIVER_VERSION 41
#define GDI_PRIORITY_NULL_DRV 0 /* null driver */ #define GDI_PRIORITY_NULL_DRV 0 /* null driver */
#define GDI_PRIORITY_FONT_DRV 100 /* any font driver */ #define GDI_PRIORITY_FONT_DRV 100 /* any font driver */
@ -235,7 +235,7 @@ struct wgl_funcs
struct wgl_context* (*p_wglCreateContext)(HDC); struct wgl_context* (*p_wglCreateContext)(HDC);
struct wgl_context* (*p_wglCreateContextAttribsARB)(HDC,struct wgl_context*,const int*); struct wgl_context* (*p_wglCreateContextAttribsARB)(HDC,struct wgl_context*,const int*);
void (*p_wglDeleteContext)(struct wgl_context*); void (*p_wglDeleteContext)(struct wgl_context*);
HDC (*p_wglGetCurrentDC)(void); HDC (*p_wglGetCurrentDC)(struct wgl_context*);
PROC (*p_wglGetProcAddress)(LPCSTR); PROC (*p_wglGetProcAddress)(LPCSTR);
BOOL (*p_wglMakeContextCurrentARB)(HDC,HDC,struct wgl_context*); BOOL (*p_wglMakeContextCurrentARB)(HDC,HDC,struct wgl_context*);
BOOL (*p_wglMakeCurrent)(HDC,struct wgl_context*); BOOL (*p_wglMakeCurrent)(HDC,struct wgl_context*);