Reputation: 167
I've decided to write my own window-wrapper kind of thing for X. I've used the example in opengl.org for creating an OpenGL 3.0 context as a starting point, and some of my code is pure copy-paste from there. I've tried the example as-it-is and it worked, but I really don't know what I'm doing wrong here. What essentially happens is this:
I get a connection to the default display.
I initialize an XVisualInfo pointer for use in window creation.
I initialize a GLXContext variable using a framebuffer configuration, which returns the said visual when calling glXGetVisualFromConfig()
I create a window, using the said visual and some attributes.
I call glXMakeCurrent() and it throws a BadMatch (invalid parameter attributes) OR I use my own error handler which says it's a segfault.
I tried skipping the glxMakeCurrent(), but it throws the same error on glXSwapBuffers()
The exact error is as follows:
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
I'm completely out of ideas here. According to this, glXSwapBuffers isn't supposed to throw a BadMatch.
Here is my code:
#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";
}
Upvotes: 1
Views: 2299
Reputation: 45322
You actually create an XColorMap
based on the visual. However, when calling XCreateWindow
, you do not set the CWColorMap
attribute bit, so this color map is not used when creating the window. This could result in the window being incompatible to the GL context created for that visual.
Upvotes: 1