wined3d: CreateFakeGLContext should also work when we have a
context [2nd try]
Jan Zerebecki
jan.wine at zerebecki.de
Wed Sep 27 23:28:59 CDT 2006
If this patch is rejected from inclusion, please tell me why, as
I would have to ask anyway.
Change from 1st try: Rediffed because of merge conflict.
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 | 197 ++++++++++++++++++++++--------------------------
1 files changed, 92 insertions(+), 105 deletions(-)
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 146ecda..826d028 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);
@@ -995,15 +993,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;
}
/**********************************************************
@@ -1273,11 +1268,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 */
@@ -1462,7 +1454,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;
@@ -1478,15 +1470,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)) {
@@ -1496,14 +1485,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");
@@ -1547,6 +1532,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,
@@ -1556,32 +1547,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