我决定为 X 编写自己的窗口包装器类型的东西。我使用 opengl.org 中的示例来创建 OpenGL 3.0 上下文作为起点,我的一些代码是从那里纯粹复制粘贴. 我已经按原样尝试了这个示例并且它有效,但我真的不知道我在这里做错了什么。本质上发生的是这样的:
我连接到默认显示。
我初始化了一个 XVisualInfo 指针以用于创建窗口。
我使用帧缓冲区配置初始化 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
我在这里完全没有想法。据此, 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";
}