glXMakeCurrent给我不好的比赛

时间:2013-04-18 22:43:44

标签: c# opengl x11 opengl-3 glx

我在使用Windows和Linux平台上的渲染系统时遇到了一些麻烦。

在Windows平台上,它的工作方式类似于sharm,而在Linux上,我的应用程序终止时出现以下异常:

  

System.InvalidOperationException:context不能是current --->   System.ComponentModel.Win32Exception:BadMatch(参数无效   属性)X错误详细信息:X事件名称:''(0)显示:0x8f17328     资源ID:4000011错误代码:8主要代码:''(135)轻微   代码:5

     

在Derm.Render.RenderContext.MakeCurrent(IDeviceContext deviceContext,Boolean flag)     在Derm.Render.RenderContext.CreateRenderContext(IDeviceContext deviceContext,Derm.Render.RenderContext hSharedContext,GLVersion version)   堆栈跟踪:

     

at(wrapper managed-to-native)System.Windows.Forms.XplatUIX11.XFlush(intptr)     在System.Windows.Forms.XplatUIX11.PostQuitMessage(int)

     

...

     

在System.Windows.Forms.Control.CreateHandle()     在System.Windows.Forms.Control.CreateControl()

我可以使用以下例程创建一个“简单”的渲染上下文:

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);
    }
}

我面临的问题是上面的上下文用于获取OpenGL信息(扩展,渲染器,...),然后被销毁。接下来,我使用属性创建上下文:

XServerDeviceContext x11DeviceContext = (XServerDeviceContext)deviceContext;

using (Glx.XLock displayLock = new Glx.XLock(x11DeviceContext.Display)) {
    return (Glx.CreateContextAttribsARB(x11DeviceContext.Display, x11DeviceContext.FBConfig, sharedContext, true, attribsList));
}

创建了上下文,但在下一个glXMakeCurrent X服务器向我发送了有问题的错误(BadMatch)。

我怀疑CreateContextAttribsARB个论点:x11DeviceContext.Displayx11DeviceContext.FBConfig。事实上,我正在使用的“drawable”实际上是一个System.Windows.Forms控件,由 Mono 实现提供。

以下是一些片段,展示了我如何初始化这些变量:

如何初始化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");

如何初始化x11DeviceContext.FBConfig

IntPtr* configs = Glx.GetFBConfigs(x11DeviceContext.Display, x11DeviceContext.Screen, out configsCount);

// Then, a value is selected using a custom seletcion algo, using GetFBConfigAttrib

很抱歉,因为我无法为您提供简短的示例程序,但代码库非常庞大且复杂。

你知道它发生了什么吗?


编辑:

进一步的调查显示,我可以使用特定的视觉效果正确渲染,否则我会得到BadMatch。我不能说为什么,但我看到了我的线条和三角形(但即使视觉不是双重缓冲,我也需要交换......)。

之前我收到BadMatch错误,因为我不知道“不符合”的视觉效果,实际上我选择了其中一个;但是,大部分视觉都给了我错误。

我已经检查了Mono实现的XplatUIX11类,并实际使用XOpenDisplay打开了显示。

2 个答案:

答案 0 :(得分:1)

  

你知道它发生了什么吗?

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

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

答案 1 :(得分:0)

我找到了解决方案。

我写了一个单元测试,为每个视觉创建OpenGL上下文,我找到了区分导致BadMatch错误的视觉效果的变量:用于创建窗口的视觉的depth

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

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