I'm having some trouble to have a rendering system working on both Windows and Linux platforms.
On Windows platform it works like a sharm, while on Linux my application terminates with the following exception:
System.InvalidOperationException: context cannot be current ---> System.ComponentModel.Win32Exception: BadMatch (invalid parameter attributes) X error details: X event name: '' (0) Display: 0x8f17328 Resource ID: 4000011 Error code: 8 Major code: '' (135) Minor code: 5
at Derm.Render.RenderContext.MakeCurrent (IDeviceContext deviceContext, Boolean flag) at Derm.Render.RenderContext.CreateRenderContext (IDeviceContext deviceContext, Derm.Render.RenderContext hSharedContext, GLVersion version) Stacktrace:
at (wrapper managed-to-native) System.Windows.Forms.XplatUIX11.XFlush (intptr) at System.Windows.Forms.XplatUIX11.PostQuitMessage (int)
...
at System.Windows.Forms.Control.CreateHandle () at System.Windows.Forms.Control.CreateControl()
I'm able to create a "simple" rendering context, using the following routine:
private static IntPtr CreateX11SimpleContext(IDeviceContext rDevice)
{
XServerDeviceContext x11DeviceCtx = (XServerDeviceContext)rDevice;
using (new Glx.XLock(x11DeviceCtx.Display)) {
int[] attributes = new int[] {
Glx.RENDER_TYPE, (int)Glx.RGBA_BIT,
0
};
// Get basic visual
unsafe {
int[] choosenConfigCount = new int[1];
IntPtr *choosenConfigs = Glx.ChooseFBConfig(x11DeviceCtx.Display, x11DeviceCtx.Screen, attributes, ref choosenConfigCount);
if (choosenConfigCount[0] == 0)
throw new InvalidOperationException("unable to find basic visual");
IntPtr choosenConfig = *choosenConfigs;
IntPtr visual = Glx.GetVisualFromFBConfig(x11DeviceCtx.Display, choosenConfig);
x11DeviceCtx.XVisualInfo = (Glx.XVisualInfo)Marshal.PtrToStructure(visual, typeof(Glx.XVisualInfo));
x11DeviceCtx.FBConfig = choosenConfig;
Glx.XFree((IntPtr)choosenConfigs);
}
// Create direct context
IntPtr rContext = Glx.CreateContext(x11DeviceCtx.Display, x11DeviceCtx.XVisualInfo, IntPtr.Zero, true);
if (rContext == IntPtr.Zero) {
// Fallback to not direct context
rContext = Glx.CreateContext(x11DeviceCtx.Display, x11DeviceCtx.XVisualInfo, IntPtr.Zero, false);
}
if (rContext == IntPtr.Zero)
throw new InvalidOperationException("unable to create context");
return (rContext);
}
}
The problem I'm facing is that the above context is used for fetching the OpenGL informations (extensions, renderer, ...), and then is destroyed. Successively, I create a context using attributes:
XServerDeviceContext x11DeviceContext = (XServerDeviceContext)deviceContext;
using (Glx.XLock displayLock = new Glx.XLock(x11DeviceContext.Display)) {
return (Glx.CreateContextAttribsARB(x11DeviceContext.Display, x11DeviceContext.FBConfig, sharedContext, true, attribsList));
}
The context is created, but at the next glXMakeCurrent
the X server send me the error in question (BadMatch).
I've suspected about the CreateContextAttribsARB
arguments: x11DeviceContext.Display
and x11DeviceContext.FBConfig
. Infact, the "drawable" I'm using is actually a System.Windows.Forms
control, provided by Mono implementation.
Here is some snippets showing how I initialize those variables:
How do I initialize x11DeviceContext.Display
?
Type xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms");
Type xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms");
if (xplatui == null)
throw new PlatformNotSupportedException("mono runtime version no supported");
// Get System.Windows.Forms display
mDisplay = (IntPtr)xplatui.GetField("DisplayHandle", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null);
if (mDisplay == IntPtr.Zero)
throw new InvalidOperationException("unable to connect to X server");
How do I initialize x11DeviceContext.FBConfig
?
IntPtr* configs = Glx.GetFBConfigs(x11DeviceContext.Display, x11DeviceContext.Screen, out configsCount);
// Then, a value is selected using a custom seletcion algo, using GetFBConfigAttrib
Sorry because I'm not able to give you a short example program, but the code base is very large and complex.
Do you have any idea to what it's going on?
EDIT:
Further investigations revealed that I can correctly render using specific visuals, otherwise I get a BadMatch
. I can't say why, but I see my lines and triangles (but I need to swap even if the visual is not double buffered...).
Previously I got the BadMatch
error because I was not aware of "not conformant" visual, indeed I selected one of them; however, most of the visual give me the error.
I've checked the XplatUIX11
class of the Mono implementation, and actually open the display with XOpenDisplay
.