Roderick Colenbrander : wgl: Get rid of delayed GLX context creation. Instead attempt to re-create a context when wglShareLists is called.

Alexandre Julliard julliard at winehq.org
Mon Nov 16 11:44:03 CST 2009


Module: wine
Branch: master
Commit: f4b88e34ec5fa9c05dd803b517ff345aa8b87801
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=f4b88e34ec5fa9c05dd803b517ff345aa8b87801

Author: Roderick Colenbrander <thunderbird2k at 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;
 }




More information about the wine-cvs mailing list