0

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.

4

2 回答 2

1

你知道发生了什么吗?

只能猜测。对我来说,这个问题听起来好像上下文已经在其他一些线程中处于活动状态,并且 glXMakeCurrent 报告它无法使上下文处于活动状态,因此;OpenGL 上下文一次只能在一个线程中处于活动状态。

我也对什么感到困惑Glx.XLock(我只能猜测它是 XLockDisplay 的对应物,因为它需要一个显示参数)?您正在使用哪些 C# OpenGL 绑定,以便我可以阅读文档?

于 2013-04-19T09:12:13.660 回答
1

我找到了解决方案。

我编写了一个单元测试,为每个视觉对象创建 OpenGL 上下文,并且我找到了区分导致BadMatch错误的视觉对象的变量:用于创建窗口的视觉对象的深度。

具有 32 位深度的视觉效果会导致BadMatch错误。幸运的是,该驱动程序提供了具有 24 位深度的等效视觉效果,效果非常好。

使用 Mono 的System.Windows.Forms.XPlatUIX11实现,窗口由框架创建(在我的例子中是 UserControl)。由于它使用CopyFromParent常量,我的控件继承了视觉深度,限制了可能的视觉选择。

于 2013-06-15T19:35:57.597 回答