wined3d: CreateFakeGLContext should also work when we have a context

Jan Zerebecki jan.wine at zerebecki.de
Mon Sep 25 04:53:48 CDT 2006


If this patch is rejected from inclusion, please tell me why, as
I would have to ask anyway.

From: Jan Zerebecki <jan.wine at zerebecki.de>
Changelog:
wined3d: CreateFakeGLContext should also work when we have a context
from somewhere else. This also fixes all the calling functions
for the changed behaviour.
---

 dlls/wined3d/directx.c |  197 ++++++++++++++++++++++--------------------------
 1 files changed, 92 insertions(+), 105 deletions(-)

diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 1baf22e..862cecf 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -72,30 +72,56 @@ DWORD minMipLookup[WINED3DTEXF_ANISOTROP
  * ie there is no GL Context - Get a default rendering context to enable the
  * function query some info from GL
  */
+
+static void WineD3D_ReleaseFakeGLContext(WineD3D_Context* ctx) {
+    if (ctx) {
+        TRACE_(d3d_caps)("decrementing ref on context from %li\n", ctx->ref);
+        if (0 == InterlockedDecrement(&ctx->ref)) {
+            /* visInfo is NULL when this is not a fake context, 
+             * but one from somewhere else. */
+            if(ctx->visInfo && ctx->glCtx) {
+                TRACE_(d3d_caps)("destroying fake GL context\n");
+                glXMakeCurrent(ctx->display, None, NULL);
+                glXDestroyContext(ctx->display, ctx->glCtx);
+            }
+            TRACE_(d3d_caps)("clearing WineD3D_Context\n");
+            ctx->glCtx = NULL;
+            ctx->visInfo = NULL;
+            ctx->display = NULL;
+            ctx->drawable = 0;
+            LEAVE_GL();
+        }
+    }
+}
+
 static WineD3D_Context* WineD3D_CreateFakeGLContext(void) {
     static WineD3D_Context ctx = { NULL, NULL, NULL, 0, 0 };
     WineD3D_Context* ret = NULL;
+    HDC device_context;
+
+    TRACE_(d3d_caps)("getting context...\n");
+
+    ctx.drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
+
+    /* Get the display */
+    device_context = GetDC(0);
+    ctx.display = get_display(device_context);
+    ReleaseDC(0, device_context);
+
+    ctx.glCtx = glXGetCurrentContext();
+
+    ENTER_GL();
 
-    if (glXGetCurrentContext() == NULL) {
-       BOOL         gotContext  = FALSE;
-       BOOL         created     = FALSE;
+    if (!ctx.glCtx) {
+        /*TODO: indentation, check if some stuff in ctx must be freed*/
        XVisualInfo  template;
-       HDC          device_context;
        Visual*      visual;
-       BOOL         failed = FALSE;
        int          num;
        XWindowAttributes win_attr;
-       TRACE_(d3d_caps)("Creating Fake GL Context\n");
 
-       ctx.drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
-
-       /* Get the display */
-       device_context = GetDC(0);
-       ctx.display = get_display(device_context);
-       ReleaseDC(0, device_context);
+       TRACE_(d3d_caps)("Creating Fake GL Context\n");
 
        /* Get the X visual */
-       ENTER_GL();
        if (XGetWindowAttributes(ctx.display, ctx.drawable, &win_attr)) {
            visual = win_attr.visual;
        } else {
@@ -103,59 +129,36 @@ static WineD3D_Context* WineD3D_CreateFa
        }
        template.visualid = XVisualIDFromVisual(visual);
        ctx.visInfo = XGetVisualInfo(ctx.display, VisualIDMask, &template, &num);
-       if (ctx.visInfo == NULL) {
-           LEAVE_GL();
+       if (!ctx.visInfo) {
            WARN_(d3d_caps)("Error creating visual info for capabilities initialization\n");
-           failed = TRUE;
+           goto exit;
        }
 
        /* Create a GL context */
-       if (!failed) {
-           ctx.glCtx = glXCreateContext(ctx.display, ctx.visInfo, NULL, GL_TRUE);
-
-           if (ctx.glCtx == NULL) {
-               LEAVE_GL();
-               WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
-               failed = TRUE;
-           }
+       ctx.glCtx = glXCreateContext(ctx.display, ctx.visInfo, NULL, GL_TRUE);
+       if (!ctx.glCtx) {
+           WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
+           goto exit;
        }
 
        /* Make it the current GL context */
-       if (!failed && glXMakeCurrent(ctx.display, ctx.drawable, ctx.glCtx) == False) {
-           glXDestroyContext(ctx.display, ctx.glCtx);
-           LEAVE_GL();
+       if (!glXMakeCurrent(ctx.display, ctx.drawable, ctx.glCtx)) {
            WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
-           failed = TRUE;
+           goto exit;
        }
 
-       /* It worked! Wow... */
-       if (!failed) {
-           gotContext = TRUE;
-           created = TRUE;
-           ret = &ctx;
-       } else {
-           ret = NULL;
-       }
+    }
 
-   } else {
-     if (ctx.ref > 0) ret = &ctx;
-   }
+    ret = &ctx;
 
-   if (NULL != ret) InterlockedIncrement(&ret->ref);
-   return ret;
-}
-
-static void WineD3D_ReleaseFakeGLContext(WineD3D_Context* ctx) {
-    /* If we created a dummy context, throw it away */
-    if (NULL != ctx) {
-        if (0 == InterlockedDecrement(&ctx->ref)) {
-            glXMakeCurrent(ctx->display, None, NULL);
-            glXDestroyContext(ctx->display, ctx->glCtx);
-            ctx->display = NULL;
-            ctx->glCtx = NULL;
-            LEAVE_GL();
-        }
+  exit:
+    if (ret)
+        InterlockedIncrement(&ret->ref);
+    else {
+        ctx.ref = 1;
+        WineD3D_ReleaseFakeGLContext(&ctx);
     }
+    return ret;
 }
 
 /**********************************************************
@@ -292,18 +295,13 @@ BOOL IWineD3DImpl_FillGLCaps(IWineD3D *i
     GLfloat     gl_floatv[2];
     Bool        test = 0;
     int         major, minor;
-    WineD3D_Context *fake_ctx = NULL;
-    BOOL        gotContext    = FALSE;
+    WineD3D_Context *fake_ctx;
+    BOOL        ret = TRUE;
     int         i;
 
     /* Make sure that we've got a context */
-    if (glXGetCurrentContext() == NULL) {
-        /* TODO: CreateFakeGLContext should really take a display as a parameter  */
-        fake_ctx = WineD3D_CreateFakeGLContext();
-        if (NULL != fake_ctx) gotContext = TRUE;
-    } else {
-        gotContext = TRUE;
-    }
+    /* TODO: CreateFakeGLContext should really take a display as a parameter  */
+    fake_ctx = WineD3D_CreateFakeGLContext();
 
     TRACE_(d3d_caps)("(%p, %p)\n", gl_info, display);
 
@@ -980,15 +978,12 @@ #undef USE_GL_FUNC
         }
     }
 
-    /* If we created a dummy context, throw it away */
-    if (NULL != fake_ctx) WineD3D_ReleaseFakeGLContext(fake_ctx);
 
     /* Only save the values obtained when a display is provided */
-    if (fake_ctx == NULL) {
-        return TRUE;
-    } else {
-        return FALSE;
-    }
+    if (fake_ctx->visInfo)
+        ret = FALSE;
+    WineD3D_ReleaseFakeGLContext(fake_ctx);
+    return ret;
 }
 
 /**********************************************************
@@ -1258,11 +1253,8 @@ static HRESULT WINAPI IWineD3DImpl_GetAd
            reuse the values once we have a context which is valid. Values from
            a temporary context may differ from the final ones                 */
         if (isGLInfoValid == FALSE) {
-            WineD3D_Context *fake_ctx = NULL;
-            if (glXGetCurrentContext() == NULL) fake_ctx = WineD3D_CreateFakeGLContext();
             /* If we don't know the device settings, go query them now */
             isGLInfoValid = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
-            if (fake_ctx != NULL) WineD3D_ReleaseFakeGLContext(fake_ctx);
         }
 
         /* If it worked, return the information requested */
@@ -1447,7 +1439,7 @@ static HRESULT WINAPI IWineD3DImpl_Check
                                                    WINED3DFORMAT DepthStencilFormat) {
     IWineD3DImpl *This = (IWineD3DImpl *)iface;
     HRESULT hr = WINED3DERR_NOTAVAILABLE;
-    WineD3D_Context* ctx = NULL;
+    WineD3D_Context* ctx;
     GLXFBConfig* cfgs = NULL;
     int nCfgs = 0;
     int it;
@@ -1463,15 +1455,12 @@ static HRESULT WINAPI IWineD3DImpl_Check
         TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
         return WINED3DERR_INVALIDCALL;
     }
-    /* TODO: use the real context if it's available */
+
     ctx = WineD3D_CreateFakeGLContext();
-    if(NULL !=  ctx) {
+    if(ctx)
         cfgs = glXGetFBConfigs(ctx->display, DefaultScreen(ctx->display), &nCfgs);
-    } else {
-        TRACE_(d3d_caps)("(%p) : Unable to create a fake context at this time (there may already be an active context)\n", This);
-    }
 
-    if (NULL != cfgs) {
+    if (cfgs) {
         for (it = 0; it < nCfgs; ++it) {
             if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx, cfgs[it], RenderTargetFormat)) {
                 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(ctx, cfgs[it], DepthStencilFormat)) {
@@ -1481,14 +1470,10 @@ static HRESULT WINAPI IWineD3DImpl_Check
             }
         }
         XFree(cfgs);
-        cfgs = NULL;
-    } else {
-        /* If there's a current context then we cannot create a fake one so pass everything */
+    } else
         hr = WINED3D_OK;
-    }
 
-    if (ctx != NULL)
-        WineD3D_ReleaseFakeGLContext(ctx);
+    WineD3D_ReleaseFakeGLContext(ctx);
 
     if (hr != WINED3D_OK)
         TRACE_(d3d_caps)("Failed to match stencil format to device\b");
@@ -1532,6 +1517,12 @@ static HRESULT WINAPI IWineD3DImpl_Check
                                             WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
 
     IWineD3DImpl *This = (IWineD3DImpl *)iface;
+    WineD3D_Context* ctx;
+    GLXFBConfig* cfgs = NULL;
+    int nCfgs = 0;
+    int it;
+    HRESULT hr = WINED3DERR_NOTAVAILABLE;
+
     TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
           This,
           Adapter,
@@ -1541,32 +1532,28 @@ static HRESULT WINAPI IWineD3DImpl_Check
           Windowed);
 
     if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
+        WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
         return WINED3DERR_INVALIDCALL;
     }
 
-    {
-      GLXFBConfig* cfgs = NULL;
-      int nCfgs = 0;
-      int it;
-      HRESULT hr = WINED3DERR_NOTAVAILABLE;
-
-      WineD3D_Context* ctx = WineD3D_CreateFakeGLContext();
-      if (NULL != ctx) {
-        cfgs = glXGetFBConfigs(ctx->display, DefaultScreen(ctx->display), &nCfgs);
-        for (it = 0; it < nCfgs; ++it) {
-            if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx, cfgs[it], DisplayFormat)) {
-                hr = WINED3D_OK;
-                break ;
-            }
-        }
-        XFree(cfgs);
-
-        WineD3D_ReleaseFakeGLContext(ctx);
-        return hr;
+    ctx = WineD3D_CreateFakeGLContext();
+    if (ctx) {
+      cfgs = glXGetFBConfigs(ctx->display, DefaultScreen(ctx->display), &nCfgs);
+      for (it = 0; it < nCfgs; ++it) {
+          if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx, cfgs[it], DisplayFormat)) {
+              hr = WINED3D_OK;
+              TRACE_(d3d_caps)("OK\n");
+              break ;
+          }
       }
+      XFree(cfgs);
+      WineD3D_ReleaseFakeGLContext(ctx);
     }
 
-    return WINED3DERR_NOTAVAILABLE;
+    if(hr != WINED3D_OK)
+        TRACE_(d3d_caps)("returning WINED3DERR_NOTAVAILABLE\n");
+
+    return hr;
 }
 
 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, 



More information about the wine-patches mailing list