Module: wine Branch: master Commit: f4b88e34ec5fa9c05dd803b517ff345aa8b87801 URL: http://source.winehq.org/git/wine.git/?a=commit;h=f4b88e34ec5fa9c05dd803b517...
Author: Roderick Colenbrander thunderbird2k@gmail.com Date: Sun Nov 15 12:09:08 2009 +0100
wgl: Get rid of delayed GLX context creation. Instead attempt to re-create a context when wglShareLists is called.
---
dlls/gdi32/opengl.c | 2 +- dlls/winex11.drv/opengl.c | 89 ++++++++++++++++++++++++++------------------- 2 files changed, 52 insertions(+), 39 deletions(-)
diff --git a/dlls/gdi32/opengl.c b/dlls/gdi32/opengl.c index 63ba433..2317afa 100644 --- a/dlls/gdi32/opengl.c +++ b/dlls/gdi32/opengl.c @@ -279,7 +279,7 @@ BOOL WINAPI wglShareLists(HGLRC hglrc1, HGLRC hglrc2) OPENGL_Context ctx = (OPENGL_Context)hglrc1;
TRACE("hglrc1: (%p); hglrc: (%p)\n", hglrc1, hglrc2); - if(ctx == NULL) + if(ctx == NULL || hglrc2 == NULL) return FALSE;
/* Retrieve the HDC associated with the context to access the display driver */ diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index 45da479..395e2a4 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -103,6 +103,8 @@ typedef struct wine_glpixelformat { typedef struct wine_glcontext { HDC hdc; BOOL do_escape; + BOOL has_been_current; + BOOL sharing; XVisualInfo *vis; WineGLPixelFormat *fmt; GLXContext ctx; @@ -1698,15 +1700,16 @@ HGLRC CDECL X11DRV_wglCreateContext(X11DRV_PDEVICE *physDev) return NULL; }
- /* The context will be allocated in the wglMakeCurrent call */ wine_tsx11_lock(); ret = alloc_context(); - wine_tsx11_unlock(); ret->hdc = hdc; ret->fmt = fmt; + ret->has_been_current = FALSE; + ret->sharing = FALSE;
- /*ret->vis = vis;*/ ret->vis = pglXGetVisualFromFBConfig(gdi_display, fmt->fbconfig); + ret->ctx = create_glxcontext(gdi_display, ret, NULL); + wine_tsx11_unlock();
TRACE(" creating context %p (GL context creation delayed)\n", ret); return (HGLRC) ret; @@ -1824,25 +1827,20 @@ BOOL CDECL X11DRV_wglMakeCurrent(X11DRV_PDEVICE *physDev, HGLRC hglrc) { ret = FALSE; } else { Drawable drawable = get_glxdrawable(physDev); - if (ctx->ctx == NULL) { - /* The describe lines below are for debugging purposes only */ - if (TRACE_ON(wgl)) { - describeDrawable(physDev); - describeContext(ctx); - }
- /* Create a GLX context using the same visual as chosen earlier in wglCreateContext. - * We are certain that the drawable and context are compatible as we only allow compatible formats. - */ - TRACE(" Creating GLX Context\n"); - ctx->ctx = create_glxcontext(gdi_display, ctx, NULL); - TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx); + /* The describe lines below are for debugging purposes only */ + if (TRACE_ON(wgl)) { + describeDrawable(physDev); + describeContext(ctx); } + TRACE(" make current for dis %p, drawable %p, ctx %p\n", gdi_display, (void*) drawable, ctx->ctx); ret = pglXMakeCurrent(gdi_display, drawable, ctx->ctx); NtCurrentTeb()->glContext = ctx; + if(ret) { + ctx->has_been_current = TRUE; ctx->hdc = hdc; ctx->read_hdc = hdc; ctx->drawables[0] = drawable; @@ -1886,10 +1884,7 @@ BOOL CDECL X11DRV_wglMakeContextCurrentARB(X11DRV_PDEVICE* pDrawDev, X11DRV_PDEV Drawable d_draw = get_glxdrawable(pDrawDev); Drawable d_read = get_glxdrawable(pReadDev);
- if (ctx->ctx == NULL) { - ctx->ctx = create_glxcontext(gdi_display, ctx, NULL); - TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx); - } + ctx->has_been_current = TRUE; ctx->hdc = pDrawDev->hdc; ctx->read_hdc = pReadDev->hdc; ctx->drawables[0] = d_draw; @@ -1918,30 +1913,48 @@ BOOL CDECL X11DRV_wglShareLists(HGLRC hglrc1, HGLRC hglrc2) {
if (!has_opengl()) return FALSE;
- if (NULL != dest && dest->ctx != NULL) { - ERR("Could not share display lists, context already created !\n"); + /* Sharing of display lists works differently in GLX and WGL. In case of GLX it is done + * at context creation time but in case of WGL it is done using wglShareLists. + * In the past we tried to emulate wglShareLists by delaying GLX context creation until + * either a wglMakeCurrent or wglShareLists. This worked fine for most apps but it causes + * issues for OpenGL 3 because there wglCreateContextAttribsARB can fail in a lot of cases, + * so there delaying context creation doesn't work. + * + * The new approach is to create a GLX context in wglCreateContext / wglCreateContextAttribsARB + * and when a program requests sharing we recreate the destination context if it hasn't been made + * current or when it hasn't shared display lists before. + */ + + if((org->has_been_current && dest->has_been_current) || dest->has_been_current) + { + ERR("Could not share display lists, one of the contexts has been current already !\n"); return FALSE; - } else { - if(org && dest && (GetObjectType(org->hdc) == OBJ_MEMDC) ^ (GetObjectType(dest->hdc) == OBJ_MEMDC)) { + } + else if(dest->sharing) + { + ERR("Could not share display lists because hglrc2 has already shared lists before\n"); + return FALSE; + } + else + { + if((GetObjectType(org->hdc) == OBJ_MEMDC) ^ (GetObjectType(dest->hdc) == OBJ_MEMDC)) + { WARN("Attempting to share a context between a direct and indirect rendering context, expect issues!\n"); }
- if (org->ctx == NULL) { - wine_tsx11_lock(); - describeContext(org); + wine_tsx11_lock(); + describeContext(org); + describeContext(dest);
- org->ctx = create_glxcontext(gdi_display, org, NULL); - wine_tsx11_unlock(); - TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org->ctx, org); - } - if (NULL != dest) { - wine_tsx11_lock(); - describeContext(dest); - dest->ctx = create_glxcontext(gdi_display, dest, org->ctx); - wine_tsx11_unlock(); - TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest->ctx, dest, org->ctx); - return TRUE; - } + /* Re-create the GLX context and share display lists */ + pglXDestroyContext(gdi_display, dest->ctx); + dest->ctx = create_glxcontext(gdi_display, dest, org->ctx); + wine_tsx11_unlock(); + TRACE(" re-created an OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest->ctx, dest, org->ctx); + + org->sharing = TRUE; + dest->sharing = TRUE; + return TRUE; } return FALSE; }