wined3d: CreateFakeGLContext should also work when we have a
context [3rd try]
Jan Zerebecki
jan.wine at zerebecki.de
Fri Oct 6 06:07:32 CDT 2006
If this patch is rejected from inclusion, please tell me why, as
I would have to ask anyway.
Patch changed according to feedback.
From: Jan Zerebecki <jan.wine at zerebecki.de>
Changelog:
wined3d: CreateFakeGLContext should also work when we have a context
from somewhere else. This fixes all the calling functions for the
changed behaviour.
---
dlls/wined3d/directx.c | 274 +++++++++++++++++++---------------------
dlls/wined3d/wined3d_main.c | 1
dlls/wined3d/wined3d_private.h | 3
include/wine/wined3d_gl.h | 8 -
4 files changed, 132 insertions(+), 154 deletions(-)
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index d405f5f..2434739 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -28,6 +28,7 @@
#include "config.h"
+#include <assert.h>
#include "wined3d_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
@@ -72,90 +73,90 @@ 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 WineD3D_Context* WineD3D_CreateFakeGLContext(void) {
- static WineD3D_Context ctx = { NULL, NULL, NULL, 0, 0 };
- WineD3D_Context* ret = NULL;
-
- if (glXGetCurrentContext() == NULL) {
- BOOL gotContext = FALSE;
- BOOL created = FALSE;
- 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);
-
- /* Get the X visual */
- ENTER_GL();
- if (XGetWindowAttributes(ctx.display, ctx.drawable, &win_attr)) {
- visual = win_attr.visual;
- } else {
- visual = DefaultVisual(ctx.display, DefaultScreen(ctx.display));
- }
- template.visualid = XVisualIDFromVisual(visual);
- ctx.visInfo = XGetVisualInfo(ctx.display, VisualIDMask, &template, &num);
- if (ctx.visInfo == NULL) {
- LEAVE_GL();
- WARN_(d3d_caps)("Error creating visual info for capabilities initialization\n");
- failed = TRUE;
- }
-
- /* 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;
- }
- }
-
- /* Make it the current GL context */
- if (!failed && glXMakeCurrent(ctx.display, ctx.drawable, ctx.glCtx) == False) {
- glXDestroyContext(ctx.display, ctx.glCtx);
- LEAVE_GL();
- WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
- failed = TRUE;
- }
-
- /* It worked! Wow... */
- if (!failed) {
- gotContext = TRUE;
- created = TRUE;
- ret = &ctx;
- } else {
- ret = NULL;
- }
-
- } else {
- if (ctx.ref > 0) ret = &ctx;
- }
-
- if (NULL != ret) InterlockedIncrement(&ret->ref);
- return ret;
+
+int wined3d_fake_gl_context_ref;
+BOOL wined3d_fake_gl_context_foreign;
+
+static Display* WineD3D_GetDisplay(void) {
+ HDC device_context = GetDC(0);
+ Display* display = get_display(device_context);
+ ReleaseDC(0, device_context);
+ return display;
+}
+
+static void WineD3D_ReleaseFakeGLContext(void) {
+ GLXContext glCtx = glXGetCurrentContext();
+ TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
+ if (0 == InterlockedDecrement(&wined3d_fake_gl_context_ref)) {
+ if(!wined3d_fake_gl_context_foreign && glCtx) {
+ TRACE_(d3d_caps)("destroying fake GL context\n");
+ glXMakeCurrent(WineD3D_GetDisplay(), None, NULL);
+ glXDestroyContext(WineD3D_GetDisplay(), glCtx);
+ }
+ LEAVE_GL();
+ }
+ assert(wined3d_fake_gl_context_ref >= 0);
}
-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();
+static void WineD3D_CreateFakeGLContext(void) {
+ TRACE_(d3d_caps)("getting context...\n");
+ if(wined3d_fake_gl_context_ref > 0) goto ret;
+ assert(0 == wined3d_fake_gl_context_ref);
+
+ wined3d_fake_gl_context_foreign = TRUE;
+ Display* display = WineD3D_GetDisplay();
+ XVisualInfo* visInfo = NULL;
+ GLXContext glCtx = glXGetCurrentContext();
+
+ ENTER_GL();
+
+ if (!glCtx) {
+ wined3d_fake_gl_context_foreign = FALSE;
+ Drawable drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");;
+
+ XVisualInfo template;
+ Visual* visual;
+ int num;
+ XWindowAttributes win_attr;
+
+ TRACE_(d3d_caps)("Creating Fake GL Context\n");
+
+ /* Get the X visual */
+ if (XGetWindowAttributes(display, drawable, &win_attr)) {
+ visual = win_attr.visual;
+ } else {
+ visual = DefaultVisual(display, DefaultScreen(display));
+ }
+ template.visualid = XVisualIDFromVisual(visual);
+ visInfo = XGetVisualInfo(display, VisualIDMask, &template, &num);
+ if (!visInfo) {
+ WARN_(d3d_caps)("Error creating visual info for capabilities initialization\n");
+ goto fail;
+ }
+
+ /* Create a GL context */
+ glCtx = glXCreateContext(display, visInfo, NULL, GL_TRUE);
+ if (!glCtx) {
+ WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
+ goto fail;
+ }
+
+ /* Make it the current GL context */
+ if (!glXMakeCurrent(display, drawable, glCtx)) {
+ WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
+ goto fail;
}
+
+ XFree(visInfo);
+
}
+
+ ret:
+ InterlockedIncrement(&wined3d_fake_gl_context_ref);
+ return;
+ fail:
+ if(visInfo) XFree(visInfo);
+ if(glCtx) glXDestroyContext(display, glCtx);
}
/**********************************************************
@@ -292,18 +293,12 @@ BOOL IWineD3DImpl_FillGLCaps(IWineD3D *i
GLfloat gl_floatv[2];
Bool test = 0;
int major, minor;
- WineD3D_Context *fake_ctx = NULL;
- BOOL gotContext = FALSE;
+ 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 */
+ WineD3D_CreateFakeGLContext();
TRACE_(d3d_caps)("(%p, %p)\n", gl_info, display);
@@ -997,15 +992,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 (wined3d_fake_gl_context_foreign)
+ ret = FALSE;
+ WineD3D_ReleaseFakeGLContext();
+ return ret;
}
/**********************************************************
@@ -1275,11 +1267,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) {
- 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 */
@@ -1329,17 +1318,17 @@ static HRESULT WINAPI IWineD3DImpl_GetAd
return WINED3D_OK;
}
-static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(WineD3D_Context* ctx, GLXFBConfig cfgs, WINED3DFORMAT Format) {
+static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(GLXFBConfig cfgs, WINED3DFORMAT Format) {
#if 0 /* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
int gl_test;
int rb, gb, bb, ab, type, buf_sz;
- gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_RED_SIZE, &rb);
- gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_GREEN_SIZE, &gb);
- gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_BLUE_SIZE, &bb);
- gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_ALPHA_SIZE, &ab);
- gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_RENDER_TYPE, &type);
- gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_BUFFER_SIZE, &buf_sz);
+ gl_test = glXGetFBConfigAttrib(WineD3D_GetDisplay(), cfgs, GLX_RED_SIZE, &rb);
+ gl_test = glXGetFBConfigAttrib(WineD3D_GetDisplay(), cfgs, GLX_GREEN_SIZE, &gb);
+ gl_test = glXGetFBConfigAttrib(WineD3D_GetDisplay(), cfgs, GLX_BLUE_SIZE, &bb);
+ gl_test = glXGetFBConfigAttrib(WineD3D_GetDisplay(), cfgs, GLX_ALPHA_SIZE, &ab);
+ gl_test = glXGetFBConfigAttrib(WineD3D_GetDisplay(), cfgs, GLX_RENDER_TYPE, &type);
+ gl_test = glXGetFBConfigAttrib(WineD3D_GetDisplay(), cfgs, GLX_BUFFER_SIZE, &buf_sz);
switch (Format) {
case WINED3DFMT_X8R8G8B8:
@@ -1399,13 +1388,13 @@ return FALSE;
#endif
}
-static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(WineD3D_Context* ctx, GLXFBConfig cfgs, WINED3DFORMAT Format) {
+static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(GLXFBConfig cfgs, WINED3DFORMAT Format) {
#if 0/* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
int gl_test;
int db, sb;
- gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_DEPTH_SIZE, &db);
- gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_STENCIL_SIZE, &sb);
+ gl_test = glXGetFBConfigAttrib(WineD3D_GetDisplay(), cfgs, GLX_DEPTH_SIZE, &db);
+ gl_test = glXGetFBConfigAttrib(WineD3D_GetDisplay(), cfgs, GLX_STENCIL_SIZE, &sb);
switch (Format) {
case WINED3DFMT_D16:
@@ -1464,7 +1453,6 @@ static HRESULT WINAPI IWineD3DImpl_Check
WINED3DFORMAT DepthStencilFormat) {
IWineD3DImpl *This = (IWineD3DImpl *)iface;
HRESULT hr = WINED3DERR_NOTAVAILABLE;
- WineD3D_Context* ctx = NULL;
GLXFBConfig* cfgs = NULL;
int nCfgs = 0;
int it;
@@ -1480,32 +1468,25 @@ 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) {
- 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) {
+ WineD3D_CreateFakeGLContext();
+ if(wined3d_fake_gl_context_ref > 0)
+ cfgs = glXGetFBConfigs(WineD3D_GetDisplay(), DefaultScreen(WineD3D_GetDisplay()), &nCfgs);
+
+ if (cfgs) {
for (it = 0; it < nCfgs; ++it) {
- if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx, cfgs[it], RenderTargetFormat)) {
- if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(ctx, cfgs[it], DepthStencilFormat)) {
+ if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(cfgs[it], RenderTargetFormat)) {
+ if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(cfgs[it], DepthStencilFormat)) {
hr = WINED3D_OK;
break ;
}
}
}
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();
if (hr != WINED3D_OK)
TRACE_(d3d_caps)("Failed to match stencil format to device\b");
@@ -1549,6 +1530,11 @@ static HRESULT WINAPI IWineD3DImpl_Check
WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
IWineD3DImpl *This = (IWineD3DImpl *)iface;
+ 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,
@@ -1558,32 +1544,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;
+ WineD3D_CreateFakeGLContext();
+ if (wined3d_fake_gl_context_ref > 0) {
+ cfgs = glXGetFBConfigs(WineD3D_GetDisplay(), DefaultScreen(WineD3D_GetDisplay()), &nCfgs);
+ for (it = 0; it < nCfgs; ++it) {
+ if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(cfgs[it], DisplayFormat)) {
+ hr = WINED3D_OK;
+ TRACE_(d3d_caps)("OK\n");
+ break ;
+ }
}
+ XFree(cfgs);
+ WineD3D_ReleaseFakeGLContext();
}
- 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,
diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c
index 872165a..746c2c8 100644
--- a/dlls/wined3d/wined3d_main.c
+++ b/dlls/wined3d/wined3d_main.c
@@ -107,6 +107,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL,
HKEY appkey = 0;
DWORD len;
wined3d_settings.emulated_textureram = 64*1024*1024;
+ wined3d_fake_gl_context_ref = 0;
DisableThreadLibraryCalls(hInstDLL);
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 659e2cf..48f64f0 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -184,6 +184,9 @@ #define ENTER_GL() wine_tsx11_lock_ptr()
#define LEAVE_GL() wine_tsx11_unlock_ptr()
#endif
+extern int wined3d_fake_gl_context_ref;
+extern BOOL wined3d_fake_gl_context_foreign;
+
/*****************************************************************************
* Defines
*/
diff --git a/include/wine/wined3d_gl.h b/include/wine/wined3d_gl.h
index 1cc6409..dbe5214 100644
--- a/include/wine/wined3d_gl.h
+++ b/include/wine/wined3d_gl.h
@@ -1795,14 +1795,6 @@ typedef struct _WineD3D_GL_Info {
} WineD3D_GL_Info;
#undef USE_GL_FUNC
-typedef struct _WineD3D_GLContext {
- GLXContext glCtx;
- XVisualInfo* visInfo;
- Display* display;
- Drawable drawable;
- LONG ref;
-} WineD3D_Context;
-
#endif /* HAVE_OPENGL */
#endif /* __WINE_WINED3D_GL */
More information about the wine-patches
mailing list