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

时间:2015-01-25 17:05:18

标签: opengl segmentation-fault glx

我决定为X编写自己的窗口包装器。我已经使用opengl.org中的示例创建了一个OpenGL 3.0上下文作为起点,并且一些我的代码是纯粹的复制粘贴。我已经尝试了这个例子并且它有效,但我真的不知道我在这里做错了什么。 基本上发生了这样的事情:

我得到了默认显示的连接。

我初始化一个XVisualInfo指针,用于创建窗口。

我使用framebuffer配置初始化一个GLXContext变量,该配置在调用glXGetVisualFromConfig()时返回所述视觉效果

我使用所述视觉和一些属性创建了一个窗口。

我调用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

我完全没有想法。根据{{​​3}},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 == '\0')
        return false;

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

        if (!where)
            break;

        terminator = where + strlen(extension);

        if ( where == start || *(where - 1) == ' ' )
            if ( *terminator == ' ' || *terminator == '\0' )
                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";
}

1 个答案:

答案 0 :(得分:1)

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