I'm trying to create a GLX context, attach it to a X Window, detach and destroy it again, then create another GLX context with a different Visual and attach it to the same window.
#include <GL/glx.h>
#include <X11/Xlib.h>
#include <stdlib.h>
#include <stdio.h>
// Descriptions for the visuals to try - if both are equal, the example works
static int attr_sets[][3] = {
{ GLX_RGBA, GLX_DOUBLEBUFFER, None },
{ GLX_RGBA, None }
};
Display *dpy;
XVisualInfo *vi;
GLXContext cxt;
Window wnd;
size_t i;
void fail(const char *m) { fprintf(stderr, "fail: %s #%lu\n", m, i+1); abort(); }
int main(void) {
dpy = XOpenDisplay(NULL);
wnd = XCreateSimpleWindow(dpy, RootWindow(dpy, 0), 0, 0, 1, 1, 1, 0, 0);
for (i = 0; i < 2; ++i) {
if (!(vi = glXChooseVisual(dpy, 0, attr_sets[1]))) fail("choose");
if (!(cxt = glXCreateContext(dpy, vi, None, True))) fail("create");
XFree(vi);
if (!glXMakeCurrent(dpy, wnd, cxt)) fail("attach");
if (!glXMakeCurrent(dpy, wnd, 0)) fail("detach");
glXDestroyContext(dpy, cxt);
}
XDestroyWindow(dpy, wnd);
XCloseDisplay(dpy);
return 0;
}
This example works on Mesa 10.5.2 with Intel graphics but fails on AMD fglrx 12.104 when the second context is attached (fail: attach #2
).
What is the reason for this error? Is this forbidden by specification or is it a driver error?
If you look at the definition of XCreateSimpleWindow
you'll see, that it's actually just a wrapper around XCreateWindow
. XCreateWindow
in turn will use the visual of it's parent.
Now X11 visuals are only half the story. When you attach a OpenGL context to a Drawable for the first time, the visual (and for the more advanced features also its FBConfig) of that Drawable may become refined, so that later on only OpenGL contexts compatible with that configurations can be attached.
In short once a Drawables Visual/FBConfig has been pinned down, only OpenGL contexts compatible to it can be attached. See the error's defined for glXMakeCurrent
, notably
BadMatch is generated if drawable was not created with the same X screen and visual as ctx. It is also generated if drawable is None and ctx is not NULL.
Normally when using GLX you'd use glXCreateWindow
to create a OpenGL exclusive subwindow in your main window, which Visual/FBConfig you can set without affecting your main window.