Question

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.

Was it helpful?

Solution 2

I found the solution.

I wrote an unit test, creating OpenGL contextes for each visual, and I found the variable that discriminate the visuals that cause the BadMatch error: the depth of the visual used for creating the window.

Visuals having a 32 bit depth cause the BadMatch error. Fortunately the driver offers equivalent visuals having 24 bit depth, which works perfectly.

Using the System.Windows.Forms.XPlatUIX11 implementation of Mono, the window is created by the framework (in my case a UserControl). Since it uses the CopyFromParent constant, my Control inherit the visual depth, limiting the possible visual to select.

OTHER TIPS

Do you have any idea to what it's going on?

Only guesses. To me this issue sounds like the context is already active in some other thread and glXMakeCurrent reports that it can not make the context active, because of that; a OpenGL context can be active in only one thread at a time.

I'm also confused about what Glx.XLock does (I can only guess it's a counterpart to XLockDisplay, given that it takes a display parameter)? Which C# OpenGL bindings are you using, so that I can read the documentation?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top