Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 6 of 6

Thread: Trouble with VAO's in linux

  1. #1
    Newbie Newbie
    Join Date
    Nov 2015
    Posts
    2

    Trouble with VAO's in linux

    I have tried to modify this code in order to draw an annulus. I am quite confused why I am getting

    OpenGL Error at displayCB()

    I know that an answer is "just use glut" but I am trying to see what goes on under the hood, so to speak.
    Am I calling Setup() at the wrong time?

    Code cpp:
    //------------------------------------------------------------------------------
    //
    //   COMPILE WITH:
    //       g++ -g -o glx_simple_new glx_simple_new.cxx -lGLU -lGL -lX11
     
    //------------------------------------------------------------------------------
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    #include <sys/time.h>
    #define GL_GLEXT_PROTOTYPES
    #define GLX_GLXEXT_PROTOTYPES
    #include <GL/gl.h>
    #include <GL/glu.h>
    #include <GL/glx.h>
     
    #define VERTICES 0
    #define INDICES 1
    #define ANNULUS 0
    #define TRIANGLE 1
     
     
    // Begin globals.
    // Vertex co-ordinate vectors for the annulus.
    static float vertices1[] =  
    {    
       30.0, 30.0, 0.0,
       10.0, 10.0, 0.0, 
       70.0, 30.0, 0.0,
       90.0, 10.0, 0.0,
       70.0, 70.0, 0.0,
       90.0, 90.0, 0.0,
       30.0, 70.0, 0.0,
       10.0, 90.0, 0.0
    };
     
    // Vertex color vectors for the annulus.
    static float colors1[] =  
    {
       0.0, 0.0, 0.0,
       1.0, 0.0, 0.0,
       0.0, 1.0, 0.0,
       0.0, 0.0, 1.0,
       1.0, 1.0, 0.0,
       1.0, 0.0, 1.0,
       0.0, 1.0, 1.0,
       1.0, 0.0, 0.0
    };
     
    // Vertex co-ordinate vectors for the triangle.
    static float vertices2[] =  
    {    
        40.0, 40.0, 0.0,
        60.0, 40.0, 0.0,
        60.0, 60.0, 0.0
    };
     
    // Vertex color vectors for the triangle.
    static float colors2[] =  
    {
        0.0, 1.0, 1.0,
        1.0, 0.0, 0.0,
        0.0, 1.0, 0.0
    };
     
    // Triangle strip vertex indices in order.
    static unsigned int stripIndices[] = {0, 1, 2, 3, 4, 5, 6, 7, 0, 1};
     
    static unsigned int buffer[2]; // Array of buffer ids.
     
    static unsigned int vao[2]; // Array of VAO ids.
     
    struct MyWin
    {
      Display  *display;
      Window    win;
      bool      displayed;
      int       width;
      int       height;
    };
     
    //----------------------------------------------------------------------------
     
    const int   WIN_XPOS    = 256;
    const int   WIN_YPOS    = 64;
    const int   WIN_XRES    = 800;
    const int   WIN_YRES    = 800;
    const int   NUM_SAMPLES = 4;
     
    //----------------------------------------------------------------------------
     
    MyWin        Win;
     
    //----------------------------------------------------------------------------
     
    double elapsedMsec( const struct timeval &start, const struct timeval &stop )
    {
      return ( ( stop.tv_sec  - start.tv_sec  ) * 1000.0 +
               ( stop.tv_usec - start.tv_usec ) / 1000.0 );
    }
     
    //----------------------------------------------------------------------------
     
    double elapsedUsec( const struct timeval &start, const struct timeval &stop )
    {
      return ( ( stop.tv_sec  - start.tv_sec  ) * 1000000.0 +
               ( stop.tv_usec - start.tv_usec ) );
    }
     
    //-----------------------------------------------------------------------------
     
    /// check() - Check for GL errors, and report any queued
     
    void check( const char hdr[] = "" )
    {
      int err;
     
      while ( ( err = glGetError() ) != GL_NO_ERROR )
        fprintf( stderr, "OpenGL Error at %s: %s\n", hdr, gluErrorString(err) );
    }
     
    //----------------------------------------------------------------------------
     
     
     
    //----------------------------------------------------------------------------
     
    void keyboardCB( KeySym sym, unsigned char key, int x, int y,
                     bool &setting_change )
    {
      switch ( tolower( key ) )
      {
        case 27:
          // ESCape - We're done!
          exit (0);
          break;
     
        case 'k':
          printf( "You hit the 'k' key\n" );
          break;
     
        case 0:
          switch ( sym )
          {
            case XK_Left  : 
              printf( "You hit the Left Arrow key\n" );
              break;
     
            case XK_Right :
              printf( "You hit the Right Arrow key\n" );
              break;
          }
          break;
      }
    }
     
    //----------------------------------------------------------------------------
     
    void reshapeCB( int width, int height )
    {
      Win.width = width;
      Win.height = height;
    }
     
    //----------------------------------------------------------------------------
     
    /** chooseFBConfig() - Try to find a framebuffer config that matches
     *    the specified pixel requirements.
     */
     
    GLXFBConfig chooseFBConfig( Display *display, int screen )
    {
      // Default template
      static const 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 attribs [ 100 ] ;
      memcpy( attribs, Visual_attribs, sizeof( Visual_attribs ) );
     
      // DELETED
     
      GLXFBConfig ret = 0;
     
      int fbcount;
      GLXFBConfig *fbc = glXChooseFBConfig( display, screen,
                                            attribs, &fbcount );
      if ( fbc )
      {
        if ( fbcount >= 1 )
          ret = fbc[0];
     
        XFree( fbc );
      }
     
      return ret;
    }
     
    //----------------------------------------------------------------------------
     
    GLXContext createContext( Display *display, int screen,
                              GLXFBConfig fbconfig, XVisualInfo *visinfo, 
                              Window window )
    {
    #define GLX_CONTEXT_MAJOR_VERSION_ARB       0x2091
    #define GLX_CONTEXT_MINOR_VERSION_ARB       0x2092
    typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
     
      // Verify 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, visinfo, 0, True );
      if ( !ctx_old ) 
      {
        printf( "Could not even allocate an old-style GL context!\n" );
        exit(1);
      }
     
      glXMakeCurrent ( display, window, ctx_old ) ;
     
      // Verify that GLX implementation supports the new context create call
      if ( strstr( glXQueryExtensionsString( display, screen ), 
                   "GLX_ARB_create_context" ) != 0 )
        glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
          glXGetProcAddress( (const GLubyte *) "glXCreateContextAttribsARB" );
     
      if ( !glXCreateContextAttribsARB )
      {
        printf( "Can't create new-style GL context\n" );
        exit(1);
      }
     
      // Got the pointer.  Nuke old context.
      glXMakeCurrent( display, None, 0 );
      glXDestroyContext( display, ctx_old );
     
      // Try to allocate a GL 4.2 COMPATIBILITY context
      static int Context_attribs[] =
      {
        GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
        GLX_CONTEXT_MINOR_VERSION_ARB, 1,
        GLX_CONTEXT_PROFILE_MASK_ARB , GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
        //GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
        //GLX_CONTEXT_FLAGS_ARB       , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
        //GLX_CONTEXT_FLAGS_ARB       , GLX_CONTEXT_DEBUG_BIT_ARB,
        None
      };
     
      GLXContext context = glXCreateContextAttribsARB( display, fbconfig, 0, 
                                                       True, Context_attribs );
     
      // Forcably wait on any resulting X errors
      XSync( display, False );
     
      if ( !context )
      {
        printf( "Failed to allocate a GL 4.2 context\n" );
        exit(1);
      }
     
      printf( "Created GL context\n" );
     
      return context;
    }
     
    //----------------------------------------------------------------------------
     
    void createWindow()
    {
      // Init X and GLX
      Win.displayed = false;
      Display *display = Win.display = XOpenDisplay( ":0.0" );
      if ( !display )
        printf( "Cannot open X display\n" );
     
      int    screen   = DefaultScreen( display );
      Window root_win = RootWindow( display, screen );
     
      if ( !glXQueryExtension( display, 0, 0 ) )
        printf( "X Server doesn't support GLX extension\n" );
     
      // Pick an FBconfig and visual
      GLXFBConfig fbconfig = chooseFBConfig( display, screen );
      if ( !fbconfig )
      {
        printf( "Failed to get GLXFBConfig\n" );
        exit(1);
      }
     
      XVisualInfo *visinfo = glXGetVisualFromFBConfig( display, fbconfig );
      if ( !visinfo )
      {
        printf( "Failed to get XVisualInfo\n" );
        exit(1);
      }
      printf( "X Visual ID = 0x%.2x\n", int( visinfo->visualid ) );
     
      // Create the X window
      XSetWindowAttributes winAttr ;
     
      winAttr.event_mask = StructureNotifyMask | KeyPressMask ;
      winAttr.background_pixmap = None ;
      winAttr.background_pixel  = 0    ;
      winAttr.border_pixel      = 0    ;
     
      winAttr.colormap = XCreateColormap( display, root_win,
                                          visinfo->visual, AllocNone );
     
      unsigned int mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask;
     
      Window win = Win.win = XCreateWindow ( display, root_win, 
                                             WIN_XPOS, WIN_YPOS, 
                                             WIN_XRES, WIN_YRES, 0, 
                                             visinfo->depth, InputOutput, 
                                             visinfo->visual, mask, &winAttr ) ;
     
      XStoreName( Win.display, win, "My GLX Window");
     
      // Create an OpenGL context and attach it to our X window
      GLXContext context = createContext( display, screen, fbconfig, visinfo, win );
     
      if ( ! glXMakeCurrent( display, win, context ) )
        printf( "glXMakeCurrent failed.\n" );
     
      if ( ! glXIsDirect ( display, glXGetCurrentContext() ) )
        printf( "Indirect GLX rendering context obtained\n" );
     
      // Display the window
      XMapWindow( display, win );
     
      if ( ! glXMakeCurrent( display, win, context ) )
        printf( "glXMakeCurrent failed.\n" );
     
      check( "createWindow()" );
     
      printf( "Window Size    = %d x %d\n", WIN_XRES, WIN_YRES );
      printf( "Window Samples = %d\n", NUM_SAMPLES );
    }
     
    //----------------------------------------------------------------------------
     
    void processXEvents( Atom wm_protocols, Atom wm_delete_window )
    {
      bool setting_change = false;
     
      while ( XEventsQueued( Win.display, QueuedAfterFlush ) )
      {
        XEvent    event;
     
        XNextEvent( Win.display, &event );
     
        if( event.xany.window != Win.win )
          continue;
     
        switch ( event.type )
        {
          case MapNotify:
            {
              Win.displayed = true;
              break;
            }
          case ConfigureNotify:
            {
              XConfigureEvent &cevent = event.xconfigure;
              reshapeCB( cevent.width, cevent.height );
              break;
            }
          case KeyPress:
            {
              char      chr;
              KeySym    symbol;
              XComposeStatus status;
     
              XLookupString( &event.xkey, &chr, 1, &symbol, &status );
     
              keyboardCB( symbol, chr, event.xkey.x, event.xkey.y,
                          setting_change );
              break;
            }
          case ClientMessage:
            {
              if ( event.xclient.message_type      == wm_protocols &&
                   Atom( event.xclient.data.l[0] ) == wm_delete_window )
              {
                //printf( "Received WM_DELETE_WINDOW\n" );
                exit(0);
              }
              break;
            }
        }
      }
    }
     
    //----------------------------------------------------------------------------
     
     
     
    //----------------------------------------------------------------------------
     
     
    void setup()
    {
       glGenVertexArrays(2, vao); // Generate VAO ids.
     
       // BEGIN bind VAO id vao[ANNULUS] to the set of vertex array calls following.
       glBindVertexArray(vao[ANNULUS]); 
     
       glGenBuffers(2, buffer); // Generate buffer ids.
     
       // Enable two vertex arrays: co-ordinates and color.
       glEnableClientState(GL_VERTEX_ARRAY);
       glEnableClientState(GL_COLOR_ARRAY);
     
       // Bind vertex buffer and reserve space.
       glBindBuffer(GL_ARRAY_BUFFER, buffer[VERTICES]);
       glBufferData(GL_ARRAY_BUFFER, sizeof(vertices1) + sizeof(colors1), NULL, GL_STATIC_DRAW);
     
       // Copy vertex coordinates data into first half of vertex buffer.
       glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices1), vertices1);
     
       // Copy vertex color data into second half of vertex buffer.
       glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertices1), sizeof(colors1), colors1);
     
       // Bind and fill indices buffer.
       glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer[INDICES]);
       glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(stripIndices), stripIndices, GL_STATIC_DRAW);
     
       // Specify vertex and color pointers to the start of the respective data.
       glVertexPointer(3, GL_FLOAT, 0, 0);
       glColorPointer(3, GL_FLOAT, 0, (GLvoid*)(sizeof(vertices1)));
       // END bind VAO id vao[ANNULUS].
     
       // BEGIN bind VAO id vao[TRIANGLE] to the set of vertex array calls following.
       glBindVertexArray(vao[TRIANGLE]);
     
       glGenBuffers(1, buffer); // Generate buffer ids.
     
       // Enable two vertex arrays: co-ordinates and color.
       glEnableClientState(GL_VERTEX_ARRAY);
       glEnableClientState(GL_COLOR_ARRAY);
     
       // Bind vertex buffer and reserve space.
       glBindBuffer(GL_ARRAY_BUFFER, buffer[VERTICES]);
       glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2) + sizeof(colors2), NULL, GL_STATIC_DRAW);
     
       // Copy vertex coordinates data into first half of vertex buffer.
       glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices2), vertices2);
     
       // Copy vertex color data into second half of vertex buffer.
       glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertices2), sizeof(colors2), colors2);
     
       // Specify vertex and color pointers to the start of the respective data.
       glVertexPointer(3, GL_FLOAT, 0, 0);
       glColorPointer(3, GL_FLOAT, 0, (GLvoid*)(sizeof(vertices2)));
       // END bind VAO id vao[TRIANGLE].
    }
     
    void displayCB()
    {
     
      glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
       // Draw annulus.
       glBindVertexArray(vao[ANNULUS]);
       glDrawElements(GL_TRIANGLE_STRIP, 10, GL_UNSIGNED_INT, 0);
     
       // Draw triangle.
       glBindVertexArray(vao[TRIANGLE]);
       glDrawArrays(GL_TRIANGLES, 0, 3);
     
      glXSwapBuffers( Win.display, Win.win );
     
      check( "displayCB()" );
    }
     
     
    void mainLoop()
    {
      // Register to receive window close events (the "X" window manager button)
      Atom wm_protocols     = XInternAtom( Win.display, "WM_PROTOCOLS"    , False);
      Atom wm_delete_window = XInternAtom( Win.display, "WM_DELETE_WINDOW", False);
      XSetWMProtocols( Win.display, Win.win, &wm_delete_window, True );
     
      while (1) 
      {
        // Redraw window (after it's mapped)
        if ( Win.displayed )
          displayCB();
     
        // Update frame rate
        static timeval last_xcheck   = {0,0};
        struct timeval now;
        gettimeofday( &now, 0 );
     
        // Check X events every 1/10 second
        if ( elapsedMsec( last_xcheck, now ) > 100 )
        {
          processXEvents( wm_protocols, wm_delete_window );
          last_xcheck = now;
        }
      }
    }
    int main( int argc, char *argv[] )
    {
     
      // Init globals
      Win.width = WIN_XRES, Win.height = WIN_YRES;
     
      // Create context and window
      createWindow();
     
      // Init OpenGL
      glViewport  ( 0, 0, Win.width, Win.height ); 
      glColorMask ( 1,1,1,1 );
      glClearColor( 0.1,0.3,0.5,1 );
      glClear     ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
     
      // Go
      printf( "Valid keys: Left, Right, k, ESC\n" );
      printf( "Press ESC to quit\n" );
      setup();
      mainLoop();
     
      return 0;
    }

    Even something as simple as a modern version of the below. I know I can not use (do not want to use) the fixed pipeline

    https://www.khronos.org/opengl/wiki/...:_GLX_and_Xlib
    Last edited by Dark Photon; 09-07-2017 at 05:17 AM.

  2. #2
    Senior Member OpenGL Pro
    Join Date
    Jan 2007
    Posts
    1,668
    And what hardware have you?

  3. #3
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    4,087
    Quote Originally Posted by HMPARTICLE View Post
    I have tried to modify this code in order to draw an annulus. I am quite confused why I am getting

    OpenGL Error at displayCB()
    Did the original version you pulled out of the forums work properly without error?

    If so, you know the problem lies with the changes you made. That helps narrow it down. Try commenting your changes out. Does the problem go away?

    You can narrow down which GL call is triggering the error by adding more calls to check() in between GL calls in the displayCB() function. If you call it before a GL call and after a GL call, and you only see it flagging a GL error after the call, you'll know it's that call that caused the error. Then look up the man page for the function and see what conditions cause it to throw that specific GL error.

    Later, you can learn how to create a DEBUG context and register a glDebugMessageCallback(). (more on that here). With this, OpenGL will call "you" when it detects that you've committed a GL error. This makes it much easier/faster to nail down which of your calls caused an error. But I wouldn't delve into this right now. Just bookmark it for later.

    Am I calling Setup() at the wrong time?
    No. You've got an active GL context then, so you're good.

    Also, to mhagain's question, let's see the output of the "glxinfo" command. Please place this output inside [code]...[/code] tags for readability.

    Finally, for any future source code snippets you add to forum posts, please place them inside [highlight=cpp]...[/highlight] or [code]...[/code] tags (note that you can use "glsl" instead of "cpp" for GLSL shader code). This makes your posts "much" more readable and so increases the likelihood that you'll get a response.

  4. #4
    Newbie Newbie
    Join Date
    Sep 2017
    Posts
    2
    Hi HMPARTICLE,

    I paste your code and run it under my machine and it gets this error
    Code :
    X Visual ID = 0xcd
    Created GL context
    Window Size    = 800 x 800
    Window Samples = 4
    Valid keys: Left, Right, k, ESC
    Press ESC to quit
    Mesa: User error: GL_INVALID_OPERATION in unsupported function called (unsupported extension or deprecated function?)
    OpenGL Error at displayCB(): invalid operation

    Looks like "glEnableClientState" is deprecated in your OpenGL version because this API is initialized as NOP. In other word, your program sets up no primitives except a fullscreen clean operation.
    I suggest you'd better try a modern way like "glVertexAttribPointer" to set up the attributes.

  5. #5
    Senior Member OpenGL Pro
    Join Date
    Jan 2007
    Posts
    1,668
    Quote Originally Posted by yuehang.wu View Post
    Looks like "glEnableClientState" is deprecated in your OpenGL version because this API is initialized as NOP. In other word, your program sets up no primitives except a fullscreen clean operation.
    I suggest you'd better try a modern way like "glVertexAttribPointer" to set up the attributes.
    No.

    The OP is explicitly creating a compatibility context, and VAOs are specified to work with legacy vertex attribs under compatibility contexts.

  6. #6
    Newbie Newbie
    Join Date
    Sep 2017
    Posts
    2
    Quote Originally Posted by mhagain View Post
    No.

    The OP is explicitly creating a compatibility context, and VAOs are specified to work with legacy vertex attribs under compatibility contexts.
    Code :
      // Try to allocate a GL 4.2 COMPATIBILITY context
      static int Context_attribs[] =
      {
        GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
        GLX_CONTEXT_MINOR_VERSION_ARB, 1,
        GLX_CONTEXT_PROFILE_MASK_ARB , GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
        //GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
        //GLX_CONTEXT_FLAGS_ARB       , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
        //GLX_CONTEXT_FLAGS_ARB       , GLX_CONTEXT_DEBUG_BIT_ARB,
        None
      };

    From his codes, the 3.1 is what he wants to create for. The Mesa does see the 3.1 version as "API_OPENGL_CORE" instead of "API_OPENGL_COMPAT", then glEnableClientStatus is initialized as NOP.

    Please refer to this line in context create from "mesa/drivers/dri/common/dri_utils.c"

    Code :
    /* Mesa does not support the GL_ARB_compatibilty extension or the
         * compatibility profile.  This means that we treat a API_OPENGL_COMPAT 3.1 as
         * API_OPENGL_CORE and reject API_OPENGL_COMPAT 3.2+.
         */
        if (mesa_api == API_OPENGL_COMPAT && major_version == 3 && minor_version == 1)
           mesa_api = API_OPENGL_CORE;

    The above assumption is based on you're running open source driver.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •