Commit ee44a199 authored by Jan Zerebecki's avatar Jan Zerebecki Committed by Alexandre Julliard

wined3d: Fix CreateFakeGLContext to work with a foreign context.

parent 10753674
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "config.h" #include "config.h"
#include <assert.h>
#include "wined3d_private.h" #include "wined3d_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d); WINE_DEFAULT_DEBUG_CHANNEL(d3d);
...@@ -66,105 +67,115 @@ DWORD *stateLookup[MAX_LOOKUPS]; ...@@ -66,105 +67,115 @@ DWORD *stateLookup[MAX_LOOKUPS];
DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1]; DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1];
typedef struct _WineD3D_GLContext {
GLXContext glCtx;
Display* display;
LONG ref;
} WineD3D_Context;
/** /**
* Note: GL seems to trap if GetDeviceCaps is called before any HWND's created * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
* ie there is no GL Context - Get a default rendering context to enable the * ie there is no GL Context - Get a default rendering context to enable the
* function query some info from GL * function query some info from GL
*/ */
static WineD3D_Context* WineD3D_CreateFakeGLContext(void) {
static WineD3D_Context ctx; static int wined3d_fake_gl_context_ref = 0;
WineD3D_Context* ret = NULL; static BOOL wined3d_fake_gl_context_foreign;
static BOOL wined3d_fake_gl_context_available = FALSE;
if (glXGetCurrentContext() == NULL) { static Display* wined3d_fake_gl_context_display = NULL;
BOOL gotContext = FALSE;
BOOL created = FALSE; static void WineD3D_ReleaseFakeGLContext(void) {
XVisualInfo template; GLXContext glCtx;
HDC device_context;
Visual* visual; if(!wined3d_fake_gl_context_available) {
BOOL failed = FALSE; TRACE_(d3d_caps)("context not available\n");
int num; return;
XVisualInfo *visInfo; }
Drawable drawable;
XWindowAttributes win_attr; glCtx = glXGetCurrentContext();
TRACE_(d3d_caps)("Creating Fake GL Context\n");
TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window"); if (0 == (--wined3d_fake_gl_context_ref) ) {
if(!wined3d_fake_gl_context_foreign && glCtx) {
/* Get the display */ TRACE_(d3d_caps)("destroying fake GL context\n");
device_context = GetDC(0); glXMakeCurrent(wined3d_fake_gl_context_display, None, NULL);
ctx.display = get_display(device_context); glXDestroyContext(wined3d_fake_gl_context_display, glCtx);
ReleaseDC(0, device_context); }
LEAVE_GL();
/* Get the X visual */ wined3d_fake_gl_context_available = FALSE;
ENTER_GL(); }
if (XGetWindowAttributes(ctx.display, drawable, &win_attr)) { assert(wined3d_fake_gl_context_ref >= 0);
visual = win_attr.visual;
} else {
visual = DefaultVisual(ctx.display, DefaultScreen(ctx.display));
}
template.visualid = XVisualIDFromVisual(visual);
visInfo = XGetVisualInfo(ctx.display, VisualIDMask, &template, &num);
if (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, visInfo, NULL, GL_TRUE);
XFree( visInfo );
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, 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;
} }
static void WineD3D_ReleaseFakeGLContext(WineD3D_Context* ctx) { static BOOL WineD3D_CreateFakeGLContext(void) {
/* If we created a dummy context, throw it away */ XVisualInfo* visInfo;
if (NULL != ctx) { GLXContext glCtx;
if (0 == InterlockedDecrement(&ctx->ref)) {
glXMakeCurrent(ctx->display, None, NULL); TRACE_(d3d_caps)("getting context...\n");
glXDestroyContext(ctx->display, ctx->glCtx); if(wined3d_fake_gl_context_ref > 0) goto ret;
ctx->display = NULL; assert(0 == wined3d_fake_gl_context_ref);
ctx->glCtx = NULL;
LEAVE_GL(); wined3d_fake_gl_context_foreign = TRUE;
if(!wined3d_fake_gl_context_display) {
HDC device_context = GetDC(0);
wined3d_fake_gl_context_display = get_display(device_context);
ReleaseDC(0, device_context);
}
ENTER_GL();
visInfo = NULL;
glCtx = glXGetCurrentContext();
if (!glCtx) {
Drawable drawable;
XVisualInfo template;
Visual* visual;
int num;
XWindowAttributes win_attr;
wined3d_fake_gl_context_foreign = FALSE;
drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
TRACE_(d3d_caps)("Creating Fake GL Context\n");
/* Get the X visual */
if (XGetWindowAttributes(wined3d_fake_gl_context_display, drawable, &win_attr)) {
visual = win_attr.visual;
} else {
visual = DefaultVisual(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display));
}
template.visualid = XVisualIDFromVisual(visual);
visInfo = XGetVisualInfo(wined3d_fake_gl_context_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(wined3d_fake_gl_context_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(wined3d_fake_gl_context_display, drawable, glCtx)) {
WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
goto fail;
}
XFree(visInfo);
} }
ret:
TRACE_(d3d_caps)("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
wined3d_fake_gl_context_ref++;
wined3d_fake_gl_context_available = TRUE;
return TRUE;
fail:
if(visInfo) XFree(visInfo);
if(glCtx) glXDestroyContext(wined3d_fake_gl_context_display, glCtx);
LEAVE_GL();
return FALSE;
} }
/********************************************************** /**********************************************************
...@@ -304,18 +315,14 @@ BOOL IWineD3DImpl_FillGLCaps(IWineD3D *iface, Display* display) { ...@@ -304,18 +315,14 @@ BOOL IWineD3DImpl_FillGLCaps(IWineD3D *iface, Display* display) {
GLfloat gl_floatv[2]; GLfloat gl_floatv[2];
Bool test = 0; Bool test = 0;
int major, minor; int major, minor;
WineD3D_Context *fake_ctx = NULL; BOOL return_value = TRUE;
BOOL gotContext = FALSE;
int i; int i;
/* Make sure that we've got a context */ /* Make sure that we've got a context */
if (glXGetCurrentContext() == NULL) { /* TODO: CreateFakeGLContext should really take a display as a parameter */
/* TODO: CreateFakeGLContext should really take a display as a parameter */ /* Only save the values obtained when a display is provided */
fake_ctx = WineD3D_CreateFakeGLContext(); if (!WineD3D_CreateFakeGLContext() || wined3d_fake_gl_context_foreign)
if (NULL != fake_ctx) gotContext = TRUE; return_value = FALSE;
} else {
gotContext = TRUE;
}
TRACE_(d3d_caps)("(%p, %p)\n", gl_info, display); TRACE_(d3d_caps)("(%p, %p)\n", gl_info, display);
...@@ -1015,15 +1022,9 @@ BOOL IWineD3DImpl_FillGLCaps(IWineD3D *iface, Display* display) { ...@@ -1015,15 +1022,9 @@ BOOL IWineD3DImpl_FillGLCaps(IWineD3D *iface, Display* display) {
} }
} }
/* 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 */ WineD3D_ReleaseFakeGLContext();
if (fake_ctx == NULL) { return return_value;
return TRUE;
} else {
return FALSE;
}
} }
/********************************************************** /**********************************************************
...@@ -1294,11 +1295,8 @@ static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Ad ...@@ -1294,11 +1295,8 @@ static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Ad
reuse the values once we have a context which is valid. Values from reuse the values once we have a context which is valid. Values from
a temporary context may differ from the final ones */ a temporary context may differ from the final ones */
if (!isGLInfoValid) { 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 */ /* If we don't know the device settings, go query them now */
isGLInfoValid = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter)); isGLInfoValid = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
if (fake_ctx != NULL) WineD3D_ReleaseFakeGLContext(fake_ctx);
} }
/* If it worked, return the information requested */ /* If it worked, return the information requested */
...@@ -1483,7 +1481,6 @@ static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT ...@@ -1483,7 +1481,6 @@ static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT
WINED3DFORMAT DepthStencilFormat) { WINED3DFORMAT DepthStencilFormat) {
IWineD3DImpl *This = (IWineD3DImpl *)iface; IWineD3DImpl *This = (IWineD3DImpl *)iface;
HRESULT hr = WINED3DERR_NOTAVAILABLE; HRESULT hr = WINED3DERR_NOTAVAILABLE;
WineD3D_Context* ctx = NULL;
GLXFBConfig* cfgs = NULL; GLXFBConfig* cfgs = NULL;
int nCfgs = 0; int nCfgs = 0;
int it; int it;
...@@ -1499,18 +1496,14 @@ static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT ...@@ -1499,18 +1496,14 @@ static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT
TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface)); TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
return WINED3DERR_INVALIDCALL; 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) { if(WineD3D_CreateFakeGLContext())
cfgs = glXGetFBConfigs(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display), &nCfgs);
if (cfgs) {
for (it = 0; it < nCfgs; ++it) { for (it = 0; it < nCfgs; ++it) {
if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx->display, cfgs[it], RenderTargetFormat)) { if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(wined3d_fake_gl_context_display, cfgs[it], RenderTargetFormat)) {
if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(ctx->display, cfgs[it], DepthStencilFormat)) { if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(wined3d_fake_gl_context_display, cfgs[it], DepthStencilFormat)) {
hr = WINED3D_OK; hr = WINED3D_OK;
break ; break ;
} }
...@@ -1523,8 +1516,7 @@ static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT ...@@ -1523,8 +1516,7 @@ static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT
hr = WINED3D_OK; hr = WINED3D_OK;
} }
if (ctx != NULL) WineD3D_ReleaseFakeGLContext();
WineD3D_ReleaseFakeGLContext(ctx);
if (hr != WINED3D_OK) if (hr != WINED3D_OK)
TRACE_(d3d_caps)("Failed to match stencil format to device\n"); TRACE_(d3d_caps)("Failed to match stencil format to device\n");
...@@ -1572,7 +1564,6 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter ...@@ -1572,7 +1564,6 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter
int nCfgs = 0; int nCfgs = 0;
int it; int it;
HRESULT hr = WINED3DERR_NOTAVAILABLE; HRESULT hr = WINED3DERR_NOTAVAILABLE;
WineD3D_Context* ctx;
TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n", TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
This, This,
...@@ -1587,18 +1578,17 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter ...@@ -1587,18 +1578,17 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter
return WINED3DERR_INVALIDCALL; return WINED3DERR_INVALIDCALL;
} }
ctx = WineD3D_CreateFakeGLContext(); if (WineD3D_CreateFakeGLContext()) {
if (NULL != ctx) { cfgs = glXGetFBConfigs(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display), &nCfgs);
cfgs = glXGetFBConfigs(ctx->display, DefaultScreen(ctx->display), &nCfgs);
for (it = 0; it < nCfgs; ++it) { for (it = 0; it < nCfgs; ++it) {
if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx->display, cfgs[it], DisplayFormat)) { if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(wined3d_fake_gl_context_display, cfgs[it], DisplayFormat)) {
hr = WINED3D_OK; hr = WINED3D_OK;
TRACE_(d3d_caps)("OK\n"); TRACE_(d3d_caps)("OK\n");
break ; break ;
} }
} }
if(cfgs) XFree(cfgs); if(cfgs) XFree(cfgs);
WineD3D_ReleaseFakeGLContext(ctx); WineD3D_ReleaseFakeGLContext();
} }
if(hr != WINED3D_OK) if(hr != WINED3D_OK)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment