Hi folks,
This is my very first post in this forum, actually I’m quite a noob in OpenGL, and I should say in visualization too.
I’m trying to create and use an OpenGL 3.x context with the Qt framework, using a subclass of QWidget (and not QGLWidget).
Firstly, I looked on Google, and it seems that nobody did this, or at least nodody shared. There is a similar post in the OpenGL on Windows forum, but I don’t think the poster made it eventually.
Actually I almost made it : I succeeded in creating a 3.0 context, but without alpha blending, and this is my issue … When I ask within a visual attributes array a GLX_ALPHA_SIZE of 8 for my context, context is created, but then I get a BadMatch X error when calling glXMakeCurrent. When I remove the GLX_ALPHA_SIZE, it do works, I can use my context, but without any transparency …
Here is the piece of code initializing OpenGL inside my derived QWidget class :
void GL3Widget::init_gl3() {
if(initialized_ == true)
return;
display_=XOpenDisplay(0);
QX11Info current_x11_info;
XVisualInfo *current_vi=(XVisualInfo*)current_x11_info.visual();
printf("Current visual ID 0x%x
", (unsigned int)current_vi -> visualid);
// Get a matching FB config
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_DOUBLEBUFFER , true,
None
};
printf( "Getting matching framebuffer configs
" );
int fbcount;
GLXFBConfig *fbc = glXChooseFBConfig( display_, DefaultScreen( display_ ),
visual_attribs, &fbcount );
if ( !fbc )
{
printf( "Failed to retrieve a framebuffer config
" );
exit(1);
}
printf( "Found %d matching FB configs.
", fbcount );
// Pick the FB config/visual with the most samples per pixel
printf( "Getting XVisualInfos
" );
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, visual_id, red_size, blue_size, green_size, alpha_size;
glXGetFBConfigAttrib( display_, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf );
glXGetFBConfigAttrib( display_, fbc[i], GLX_SAMPLES , &samples );
glXGetFBConfigAttrib( display_, fbc[i], GLX_VISUAL_ID , &visual_id );
glXGetFBConfigAttrib( display_, fbc[i], GLX_RED_SIZE , &red_size );
glXGetFBConfigAttrib( display_, fbc[i], GLX_BLUE_SIZE , &blue_size );
glXGetFBConfigAttrib( display_, fbc[i], GLX_GREEN_SIZE , &green_size );
glXGetFBConfigAttrib( display_, fbc[i], GLX_ALPHA_SIZE , &alpha_size );
printf( " Matching fbconfig %d, visual ID 0x%x , SAMPLE_BUFFERS = %d,"
" SAMPLES = %d R:%d G:%d B:%d A%d
",
i, visual_id, samp_buf, samples, red_size, blue_size, green_size, alpha_size);
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 );
}
// Get a visual
int fbc_id = best_fbc;
XVisualInfo *vi = glXGetVisualFromFBConfig( display_, fbc[ fbc_id ] );
printf( "Chosen visual ID = 0x%x
", (unsigned int)vi->visualid );
// See if GL driver supports glXCreateContextAttribsARB()
// Create an old-style GLX context first, to get the correct function ptr.
glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
GLXContext ctx_old=glXCreateContext( display_, vi, 0, true );
glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
glXGetProcAddress( (const GLubyte *) "glXCreateContextAttribsARB" );
ctxt_ = 0;
// If it doesn't, just use the old-style 2.x GLX context
if ( !glXCreateContextAttribsARB )
{
printf( "glXCreateContextAttribsARB() not found"
" ... using old-style GLX context
" );
ctxt_ = ctx_old;
}
// If it "does", try to get a GL 3.0 context!
else
{
glXMakeCurrent( display_, 0, 0 );
glXDestroyContext( display_, ctx_old );
static int context_attribs[] =
{
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 0,
None
};
printf( "Creating context
" );
ctxt_ = glXCreateContextAttribsARB( display_, fbc[ fbc_id ], 0,
true, context_attribs );
if ( ctxt_ )
printf( "Created GL 3.0 context
" );
else
{
// Couldn't create GL 3.0 context. Fall back to old-style 2.x context.
printf( "Failed to create GL 3.0 context"
" ... using old-style GLX context
" );
ctxt_ = glXCreateContext( display_, vi, 0, true );
}
}
XFree( fbc );
// Verifying that context is a direct context
printf( "Verifying that context is direct
" );
if ( ! glXIsDirect ( display_, ctxt_ ) )
{
printf( "Indirect GLX rendering context obtained" );
exit(1);
}
printf( "Making context current on drawable 0x%x ...
", (unsigned int)winId() );
if(!glXMakeCurrent( display_, winId(), ctxt_ )) {
printf( "glxMakeCurrent failed :-/
" );
exit(1);
}
glClearColor ( 0, 0.0, 1, 1 );
glClear ( GL_COLOR_BUFFER_BIT );
initialized_=true;
}
Most of this code comes from the OpenGL 3.0 and GLX tutorial on the wiki, I just tried to integrate it within Qt.
Hardware info : Nvidia GTX260 with latest 190.something OpenGL 3.2 drivers, running on Ubuntu 9.04 64 bits.
So to sum-up, if i comment out the GLX_ALPHA_SIZE line, i get a working context, but without transparency. If i keep the line, i get a XError : BadMatch on the glxMakeCurrent call.
Any idea or suggestion about what could be wrong ?
Thanks !
PS : if anyone is interested in testing the code, I can try to post the whole code with the qmake .pro file (very small, ~200 lines), is it possible to attach a file in this forum ?