From: Rémi Bernon rbernon@codeweavers.com
Allowing re-sharing of contexts as long as they haven't been modified, although this isn't enough to fix some games which even modify the contexts before sharing them. --- dlls/opengl32/tests/opengl.c | 2 -- dlls/opengl32/unix_wgl.c | 39 ++++++++++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 4 deletions(-)
diff --git a/dlls/opengl32/tests/opengl.c b/dlls/opengl32/tests/opengl.c index 899b695e518..5e8a570f915 100644 --- a/dlls/opengl32/tests/opengl.c +++ b/dlls/opengl32/tests/opengl.c @@ -1145,12 +1145,10 @@ static void test_sharelists(HDC winhdc) if (dest_sharing) { res = wglShareLists(other, dest); - todo_wine_if(source_sharing && dest_current) ok(res, "Sharing of display lists from other to dest failed\n"); }
res = wglShareLists(source, dest); - todo_wine_if((source_current || source_sharing) && (dest_current || dest_sharing)) ok(res || broken(nvidia && !source_sharing && dest_sharing), "Sharing of display lists from source to dest failed\n");
diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index 87f665f338b..b803759242d 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -122,10 +122,36 @@ static struct wgl_handle *get_handle_ptr( HANDLE handle ) return NULL; }
+static struct opengl_context *opengl_context_from_handle( HGLRC handle, const struct opengl_funcs **funcs ); + +/* update handle context if it has been re-shared with another one */ +static void update_handle_context( struct wgl_handle *ptr ) +{ + struct opengl_context *ctx = ptr->u.context, *shared; + const struct opengl_funcs *funcs = ptr->funcs, *share_funcs; + struct wgl_context *(*func)( HDC hDC, struct wgl_context * hShareContext, const int *attribList ); + struct wgl_context *prev = ctx->drv_ctx, *drv_ctx; + + if (ctx->tid || ctx->used) return; /* used already */ + if (ctx->share == (HGLRC)-1) return; /* not re-shared */ + if (!(func = funcs->p_wglCreateContextAttribsARB)) func = (void *)funcs->p_wglGetProcAddress( "wglCreateContextAttribsARB" ); + if (!func) return; /* not supported */ + + shared = ctx->share ? opengl_context_from_handle( ctx->share, &share_funcs ) : NULL; + if (!(drv_ctx = func( ctx->hdc, shared->drv_ctx, ctx->attribs ))) + { + WARN( "Failed to re-create context for wglShareLists\n" ); + return; + } + ctx->drv_ctx = drv_ctx; + funcs->p_wglDeleteContext( prev ); +} + static struct opengl_context *opengl_context_from_handle( HGLRC handle, const struct opengl_funcs **funcs ) { struct wgl_handle *entry; if (!(entry = get_handle_ptr( handle ))) return NULL; + update_handle_context( entry ); *funcs = entry->funcs; return entry->u.context; } @@ -715,6 +741,7 @@ HGLRC wrap_wglCreateContext( TEB *teb, HDC hdc ) if ((context = calloc( 1, sizeof(*context) ))) { context->hdc = hdc; + context->share = (HGLRC)-1; /* initial shared context */ context->drv_ctx = drv_ctx; if (!(ret = alloc_handle( HANDLE_CONTEXT, funcs, context ))) free( context ); } @@ -801,7 +828,15 @@ BOOL wrap_wglShareLists( TEB *teb, HGLRC hglrcSrc, HGLRC hglrcDst ) if (!(src = opengl_context_from_handle( hglrcSrc, &src_funcs ))) return FALSE; if (!(dst = opengl_context_from_handle( hglrcDst, &dst_funcs ))) return FALSE; if (src_funcs != dst_funcs) RtlSetLastWin32Error( ERROR_INVALID_HANDLE ); - else ret = src_funcs->p_wglShareLists( src->drv_ctx, dst->drv_ctx ); + else if ((ret = !src->used)) src->share = hglrcDst; + else + { + /* Windows allows sharing even after contexts have been used, + * we will need to implement wglCopyContext for that + */ + FIXME( "Failed to share %p with %p, context has been used\n", hglrcSrc, hglrcDst ); + } + return ret; }
@@ -836,7 +871,7 @@ HGLRC wrap_wglCreateContextAttribsARB( TEB *teb, HDC hdc, HGLRC share, const int if ((context = calloc( 1, sizeof(*context) ))) { context->hdc = hdc; - context->share = share; + context->share = (HGLRC)-1; /* initial shared context */ context->attribs = memdup_attribs( attribs ); context->drv_ctx = drv_ctx; if (!(ret = alloc_handle( HANDLE_CONTEXT, funcs, context ))) free( context );