Opengl3.x and Qt under Linux

Hi!

I currently try too create a Opengl3.x compatible QWidget under Linux. I use some source from this post:

http://www.opengl.org/discussion_boards
/ubbthreads.php?ubb=showflat&Number=262519

The context opens without an error, but the window is not created on my MainWindow. Instead there is a new window next to my gui. Any idea how i can embed the context on my gui-window? Have anybody a working example?

Code looks like that:

main.cpp:


 int main(int argc, char *argv[])
      {
          QApplication app(argc, argv);
     
          MainWindow mainwindow;
          mainwindow.show();
          return app.exec();
 }

mainwindow.cpp


MainWindow::MainWindow(QWidget *parent)
         : QMainWindow(parent)
     {
         ui.setupUi(this);
         connect(ui.mButtonTest,SIGNAL(clicked()),this,SLOT(printHello()));
 }


The newly created QWidget with the gl3-context is set on the mainwindow with the qtdesigner and looks like that


GL3Widget::GL3Widget(QWidget *parent):
             QWidget(parent)
     {   
         
         
         initWindow();
     
     }    

Init Framebuffer:


 void GL3Widget::initWindow()
     {
         setAttribute(Qt::WA_PaintOnScreen);
         setAttribute(Qt::WA_NoSystemBackground);
         setAutoFillBackground(true);
     
         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
         };
     
         const QX11Info &xinfo = x11Info();
         Display *display = xinfo.display();
     
         XVisualInfo *vi = NULL;
         Window window = 0;
         int fbcount = 0;
     
         GLXFBConfig *fbc = glXChooseFBConfig( display, DefaultScreen( display ),
                                               visual_attribs, &fbcount );
         if ( !fbc ) {
             printf( "Failed to retrieve a framebuffer config
" );
             exit(1);
         }
     
         mFBConfig = fbc[0];
         XFree(fbc);
     
         printf( "Found %d matching FB configs.
", fbcount );
     
     
         vi = glXGetVisualFromFBConfig( display, mFBConfig );
         XSetWindowAttributes swa;
         swa.colormap = XCreateColormap( display, RootWindow( display, vi->screen )
 swa.background_pixmap = None ;
         swa.border_pixel      = 0;
         swa.event_mask        = StructureNotifyMask;
     
     
         printf( "Creating window
" );
         Window win = XCreateWindow( display, RootWindow( display, vi->screen ),
                                     0, 0, 100, 100, 0, vi->depth, InputOutput,
                                     vi->visual,
                                     CWBorderPixel | CWColormap | CWEventMask, &swa );
         if ( !win ) {
             printf( "Failed to create window.
" );
             exit(1);
         }
     
         std::cout << "QT" << std::endl;
         create(win, true, true);
     
         mGL3Context = 0;
         initContext();
     }

Create context:


void GL3Widget::initContext()
     {
         Display *display;
         {
             const QX11Info &xinfo = x11Info();
             display = xinfo.display();
         }
     
         XVisualInfo *vi = glXGetVisualFromFBConfig(display, mFBConfig);
         GLXContext tempContext = glXCreateContext(display, vi, 0, True);
     
         glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
         glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
                                      glXGetProcAddress( (const GLubyte *) "glXCreateContextAttribsARB" );
     
         glXMakeCurrent(display, 0, 0);
         glXDestroyContext(display, tempContext);
     
         int attribs[] = {
             GLX_CONTEXT_MAJOR_VERSION_ARB, 3/*requestedGLVersion.Major*/,
             GLX_CONTEXT_MINOR_VERSION_ARB, 0/*requestedGLVersion.Minor*/,
             None
         };
     
         mGL3Context = glXCreateContextAttribsARB(display, mFBConfig, 0, True, attribs);
         if (mGL3Context == NULL) {
             std::cout << "Context failed" << std::endl;
             exit(1);
         }
     
         if (glXIsDirect(display, mGL3Context) != True) {
             std::cout << "The gl context is not direct." << std::endl;
             exit(1);
         }
     
     }
     
     

Thx for help!

If you don’t need the menu just do that:


int main(int argc, char *argv[])
{
   QApplication app(argc, argv);
     
   GL3Widget mainwindow;
   mainwindow.show();
   return app.exec();
 }

When you create a widget without a parent it become an indipendent window

Otherwise you can do


MainWindow::MainWindow(QWidget *parent)
         : QMainWindow(parent), glContext(parent)
{
         ui.setupUi(this);
connect(ui.mButtonTest,SIGNAL(clicked()),this,SLOT(printHello()));
}

I know, but the problem is, when i choose your last method, 2 independent windows are created. But context-widget should placed on my MainWindow.

ehm… sorry, I didn’t tested the second solution, I always use the first. :smiley:

I imagine your MainWindow should have a private attribute like this


protected:
   GL3Widget glWig_;

As I told you before you need to pass a correct parent to your widget.

MainWindow::MainWindow(QWidget *parent)
         : QMainWindow(parent), glWig_(this)
{
   ui.setupUi(this);
   connect(ui.mButtonTest,SIGNAL(clicked()),this,SLOT(printHello()));
}

note the this pointer. In this case you have to manually resize the context every time the windows is resized.

Another (better solution) is to define a pointer to your widget and in the windows constructor call setCentralWidget like this.


MainWindow::MainWindow(QWidget *parent)
         : QMainWindow(parent)
{
   glWig_ = new Gl3Widget();
   this->setCentralWidget(glWig_);
   //....
 }

You can also use layout controller to use your openGL widget with other type of widget. Check the Qt example. :slight_smile:

BTW: Did you try to redefine only the QGLContext class and use QGLWidget? I tried but I can’t get the windows pointer and the frame buffer descriptor… are both private. :frowning:

Ok i will test it. But as far as i understand the header files generated by the QtDesigner, your last method is automatically generated. I created the gui with the designer and placed my GL3Widget on it.

BTW: Did you try to redefine only the QGLContext class and use QGLWidget? I tried but I can’t get the windows pointer and the frame buffer descriptor… are both private.

I created the context on my own in a QWidget-Class. I still wonder, why there is no working solution for this problem around the inet. Nobody working with opengl 3.x and Qt here?

I’m reading now the documentation of the new QT4.7 and it have openGl 3.2 support. Qt 4.6 support “only” ogl 3.0

http://doc.qt.nokia.com/4.7-snapshot/qglformat.html#OpenGLVersionFlag-enum

Also add the QGlBuffer to wrap VBO.

QTDesigner can create only standard widget, and is excellent to create dialog. To create custom object I prefer to write the code.