glXMakeCurrent() 和 glXSwapBuffers() 抛出 BadMatch(无效参数属性)段错误

glXMakeCurrent() and glXSwapBuffers() throwing BadMatch (invalid parameter attributes) segfault

我决定为 X 编写自己的 window-wrapper 类的东西。我使用 opengl.org 中的示例创建 OpenGL 3.0 上下文作为起点,并且我的一些 代码是从那里纯复制粘贴的。我已经按原样尝试了这个例子并且它起作用了,但我真的不知道我在这里做错了什么。 本质上发生的是这样的:

我连接到默认显示器。

我初始化了一个 XVisualInfo 指针用于 window 创建。

我使用帧缓冲区配置初始化了一个 GLXContext 变量,returns 在调用 glXGetVisualFromConfig() 时

我创建了一个 window,使用上述视觉效果和一些属性。

我调用 glXMakeCurrent() 并抛出一个 BadMatch(无效的参数属性)或者我使用我自己的错误处理程序,它说这是一个段错误。

我尝试跳过 glxMakeCurrent(),但它在 glXSwapBuffers() 上抛出相同的错误

具体错误如下:

X Error of failed request:  BadMatch (invalid parameter attributes)
    Major opcode of failed request:  1 (X_CreateWindow)
    Serial number of failed request:  33
    Current serial number in output stream:  36

我完全没有想法。根据 this,glXSwapBuffers 不应该抛出 BadMatch。

这是我的代码:

#include "X_Window.h"
#include < stdio.h >
#include < stdlib.h >
#include < string.h >
#include < unistd.h >
#include < X11/Xlib.h >
#include < X11/Xutil.h >
#include  <GL/gl.h >
#include < GL/glx.h >
#include < iostream >

using namespace Deva;
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
//static bool isDisplayInitialized = 0;
static Display* display = 0;
static GLXContext context = 0;
static XVisualInfo* vinfo = 0;
static GLXFBConfig bestFbc = 0;



static bool isExtensionSupported(const char *extList, const char *extension)
{
    const char *start;
    const char *where, *terminator;

    where = strchr(extension, ' ');
    if (where || *extension == '[=11=]')
        return false;

    for (start=extList;;)
    {
        where = strstr(start, extension);

        if (!where)
            break;

        terminator = where + strlen(extension);

        if ( where == start || *(where - 1) == ' ' )
            if ( *terminator == ' ' || *terminator == '[=11=]' )
                return true;

        start = terminator;
    }

    return false;
}

static bool contextErrorOccurred = false;
static int contextErrorHandler( Display *dpy, XErrorEvent *ev )
{
    contextErrorOccurred = true;
    char * text;
    XGetErrorText(dpy, ev->error_code, text, 300);
    std::cout << text << std::endl;
    return 0;
}


static void initializeVisualInfo()
{
    static int visual_attribs[] =
    {
        GLX_X_RENDERABLE    , True,
        GLX_DRAWABLE_TYPE   , GLX_WINDOW_BIT,
        GLX_RENDER_TYPE     , GLX_RGBA_BIT,
        GLX_X_VISUAL_TYPE   , GLX_TRUE_COLOR,
        GLX_RED_SIZE        , 8,
        GLX_GREEN_SIZE      , 8,
        GLX_BLUE_SIZE       , 8,
        GLX_ALPHA_SIZE      , 8,
        GLX_DEPTH_SIZE      , 24,
        GLX_STENCIL_SIZE    , 8,
        GLX_DOUBLEBUFFER    , True,
        //GLX_SAMPLE_BUFFERS  , 1,
        //GLX_SAMPLES         , 4,
        None
    };

    int glx_major, glx_minor;

    if ( !glXQueryVersion( display, &glx_major, &glx_minor ) ||
            ( ( glx_major == 1 ) && ( glx_minor < 3 ) ) || ( glx_major < 1 ) )
    {
        printf("Invalid GLX version");
        exit(1);
    }

    int fbcount;
    GLXFBConfig* fbc = glXChooseFBConfig(display, DefaultScreen(display), visual_attribs, &fbcount);

    if (!fbc) exit(1);

    int best_fbc = -1, worst_fbc = -1, best_num_samp = -1, worst_num_samp = 999;

    int i;
    for (i=0; i<fbcount; ++i)
    {
        XVisualInfo *vi = glXGetVisualFromFBConfig( display, fbc[i] );
        if ( vi )
        {
            int samp_buf, samples;
            glXGetFBConfigAttrib( display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf );
            glXGetFBConfigAttrib( display, fbc[i], GLX_SAMPLES       , &samples  );

            if ( best_fbc < 0 || samp_buf && samples > best_num_samp )
                best_fbc = i, best_num_samp = samples;
            if ( worst_fbc < 0 || !samp_buf || samples < worst_num_samp )
                worst_fbc = i, worst_num_samp = samples;
        }
        XFree( vi );
    }
    bestFbc = fbc[ best_fbc ];

    XFree( fbc );

    vinfo = glXGetVisualFromFBConfig( display, bestFbc );
}

static void initializeContext()
{
    const char *glxExts = glXQueryExtensionsString( display,
                          DefaultScreen( display ) );

    glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
    glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
                                 glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );

    context = 0;

    contextErrorOccurred = false;
    //int (*oldHandler)(Display*, XErrorEvent*) =
    //   XSetErrorHandler(&contextErrorHandler);

    if ( !isExtensionSupported( glxExts, "GLX_ARB_create_context" ) ||
            !glXCreateContextAttribsARB )
    {
        context = glXCreateNewContext( display, bestFbc, GLX_RGBA_TYPE, 0, True );
    }

    else
    {
        int context_attribs[] =
        {
            GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
            GLX_CONTEXT_MINOR_VERSION_ARB, 0,
            //GLX_CONTEXT_FLAGS_ARB        , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
            None
        };

        context = glXCreateContextAttribsARB( display, bestFbc, 0, True, context_attribs);

        XSync( display, False );

        if ( !contextErrorOccurred && context );
        else
        {
            context_attribs[1] = 1;
            context_attribs[3] = 0;
            contextErrorOccurred = false;
            context = glXCreateContextAttribsARB( display, bestFbc, 0,
                                                  True, context_attribs );
        }
    }

    XSync( display, False );
}

DevaWindow* DevaWindow::createWindow(unsigned int width,
                                     unsigned int height,
                                     char window_name[],
                                     int x,
                                     int y)
{
    display = XOpenDisplay(NULL);
    if(!display)
    {
        std::cout << "Couldn't connect to display. Exiting...\n";
        exit(EXIT_FAILURE);
    }
    if(!vinfo) initializeVisualInfo();
    if(!context) initializeContext();
    return new DevaWindow(width, height, window_name, x, y);
}

DevaWindow::DevaWindow(
    unsigned int width,
    unsigned int height,
    char window_name[],
    int x,
    int y
) : width(width), height(height)
{

    //auto screen_num = DefaultScreen(display);
    XSetWindowAttributes attributes;
    attributes.background_pixmap = None;
    attributes.background_pixel = BlackPixel(display, vinfo->screen);
    attributes.border_pixmap = None;
    attributes.border_pixel = WhitePixel(display, vinfo->screen);
    attributes.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask;
    Colormap cmap;
    attributes.colormap = cmap = XCreateColormap( display,
                                 RootWindow( display, vinfo->screen ),
                                 vinfo->visual, AllocNone );

    unsigned long valuemask = CWBackPixmap | CWBackPixel | CWBorderPixmap | CWBorderPixel | CWEventMask;

    std::cout << "VisualID Windows " << vinfo->visual->visualid << std::endl;
    window = XCreateWindow(display,
                           RootWindow(display, vinfo->screen),
                           x, y,
                           width, height,
                           2,
                           vinfo->depth,
                           InputOutput,
                           vinfo->visual,
                           valuemask,
                           &attributes);
    std::cout << "VIsual Window: " << vinfo <<std::endl;

    //XChangeWindowAttributes(display, window, valuemask, &attributes);

    XMapWindow(display, window);
    XEvent evnt;
    //XNextEvent(display, &evnt);
}

void DevaWindow::update()
{
    glXSwapBuffers(display, window);
    std::cout << "WHYYYYYYYYYYYYYY\n";
}

void DevaWindow::setContext()
{
    printf("Display %d, Window %i, Context %i\n", display, window, context);
    glXMakeCurrent(display, window, context);
    std::cout << "Good\n";
}

您实际上是根据视觉效果创建了一个 XColorMap。但是,在调用 XCreateWindow 时,您没有设置 CWColorMap 属性位,因此在创建 window 时不会使用此颜色映射。这可能会导致 window 与为该视觉对象创建的 GL 上下文不兼容。