Section D.2. OpenGL Errors


D.2. OpenGL Errors

Examining the OpenGL error code and identifying the OpenGL command that caused it is the single most effective debugging technique for OpenGL applications.

D.2.1. Check the OpenGL Error Code

Get in the habit of using glGetError(). To call this routine without impeding performance, use the C preprocessor. Define a macro to check for errors in development builds and act as a no-op in production builds. The OpenGL® Distilled example code uses this strategy to define the OGLDIF_CHECK_ERROR CPP macro. If _DEBUG is defined at compile time, indicating a development build, the OGLDIF_CHECK_ERROR macro expands to a call to the checkError() function:

 void checkError() {     const GLenum error = glGetError();     if (error != GL_NO_ERROR)     {         const GLubyte* errorStr = gluErrorString( error );         std::cerr << "Error: " << std::string( (char*)errorStr )             << std::endl;     }     assert( error == GL_NO_ERROR ); } #ifdef _DEBUG    // Development build: check for errors #  define OGLDIF_CHECK_ERROR checkError() #else    // Release build: no-op #  define OGLDIF_CHECK_ERROR #endif 


A good rule of thumb is to place this call once after your OpenGL initialization code and then again after every frame. If the assertion fails, look in the preceding code for errors. Add calls to glGetError() (or to your errorchecking CPP macro) throughout the suspect code to help isolate and identify the OpenGL call(s) generating the error.

D.2.2. Specific Errors

Chapter 1, "An Introduction to OpenGL," briefly discusses OpenGL errors and their causes. This section covers errors in greater detail and lists likely causes for the errors.

Note that there are numerous ways to generate errors in OpenGL. Each command description in OpenGL® Reference Manual enumerates the errors a command can generate, and under what circumstances. The OpenGL Graphics System, along with extension specifications, are the definitive resources for the errors OpenGL commands can generate.

Common causes of OpenGL errors include the following:

  • GL_INVALID_ENUM Your application passed an unacceptable enumerant to an OpenGL command that takes a GLenum as an argument.

    A common cause of GL_INVALID_ENUM is accidentally passing a similarly-named enumerant. OpenGL generates a GL_INVALID_ENUM error, for example, if your application calls glDrawElements() with GL_POINT as the mode parameter instead of GL_POINTS. (GL_POINT is a valid enumerant for the glPolygonMode() command.)

  • GL_INVALID_OPERATION Your application issued a command that wasn't allowed in the current state.

    Code that performs selection generates this error if the application places OpenGL in selection mode with glRenderMode( GL_SELECT ) before first specifying a selection buffer using the glSelectBuffer() command.

    OpenGL returns this error if your application attempts to read the depth buffer using glReadPixels(), but there is no depth buffer. The same is true if using glCopyTexImage2D() to copy depth buffer data to a depth texture. Check your init code to ensure that it creates a depth buffer.

    OpenGL also returns this error if you attempt to bind a texture object to the wrong target. Bind 2D textures to GL_TEXTURE_2D and cube map textures to GL_TEXTURE_CUBE_MAP to avoid this error.

    Applications that use the (obsolete) glBegin()/glEnd() paradigm commonly encounter this problem by issuing any one of several commands not allowed between glBegin() and glEnd() or by failing to call either glBegin() or glEnd().

    It's an error to call glGetError() between glBegin() and glEnd()GL_INVALID_OPERATION. Calls that generate errors are required by the OpenGL specification to behave as a no-op, however. For this reason, glGetError() doesn't actually return an error code when called between glBegin() and glEnd(); in fact, it returns GL_NO_ERROR. Your application must retrieve the GL_INVALID_OPERATION error later by calling glGetError() outside the glBegin()/glEnd() pair. You should avoid this somewhat quirky aspect of OpenGL errors by using vertex arrays and buffer objects instead of the glBegin()/glEnd() paradigm.

  • GL_INVALID_VALUE Your application called an OpenGL command, but at least one of the numerical parameters was out of range.

    Calling glDrawRangeElements() with the end parameter less than the start parameter will generate this error.

    When using OpenGL lighting, the specular exponent (GL_SHININESS value, set with glMaterialf()) must be in the range 0 through 128, inclusive; otherwise, OpenGL generates the GL_INVALID_VALUE error. (The GL_NV_light_max_exponent extension allows an implementation to support larger specular exponent values.)

    OpenGL also generates this error if your application specifies a cube map face that isn't square. The width and height parameters to glTexImage2D() must be equal when the target parameter indicates a cube map face.

    Accidentally passing the wrong parameter to glClear() will generate this error. glClear( GL_DEPTH ) generates this error, for example, because GL_DEPTH isn't an acceptable enumerant for the glClear() command. Instead, call glClear( GL_DEPTH_BUFFER_BIT ).

  • GL_OUT_OF_MEMORY There was insufficient memory for OpenGL to execute a command.

    Obviously, one way to generate this error is if your application has consumed too much memory. If you receive this error during development, check your process size and available total system RAM.

    OpenGL generates this error in response to a glBufferData() command if it's unable to create a data store of the required size. Check to make sure you're passing in a reasonable value for size.

    When your application creates a display list, OpenGL makes copies of all the parameters, including copies of data pointed to by address parameters. For this reason, display lists can consume large amounts of memory. The glEndList() command will generate GL_OUT_OF_MEMORY if OpenGL is unable to store all the commands and parameters between glNewList() and glEndList().

    If the OpenGL version is 1.1 or later, and glEndList() generated the GL_OUT_OF_MEMORY error, OpenGL continues to operate in a defined state. Otherwise, OpenGL behavior is undefined.

  • GL_STACK_OVERFLOW and GL_STACK_UNDERFLOW Your application pushed or popped an OpenGL stack beyond its limits.

    These errors can occur when your application manipulates one of the matrix stacks, such as the texture, model-view, or projection matrix stacks (glPushMatrix()/glPopMatrix()), either of the attribute stacks (glPushAttrib()/glPopAttrib() or glPushClientAttrib()/glPopClientAttrib()), or the name stack (glPushName()/glPopName()).

    OpenGL generates GL_STACK_UNDERFLOW when your application issues more pop commands than corresponding push commands.

    Conversely, GL_STACK_OVERFLOW occurs if you push a stack beyond its maximum number of entries. The OpenGL specification dictates a minimum stack size, but implementations may support larger stacks. Note that the projection and texture stacks can be as small as two entries.

    Applications commonly encounter this error by pushing or popping the wrong stack. Note that glPushMatrix() and glPopMatrix() affect different stacks depending on the current matrix mode, set with glMatrixMode(). Furthermore, if the matrix mode is GL_TEXTURE, the affected stack depends on the value of glActiveTexture(), because each texture unit has its own stack. As you develop your application, carefully code push and pop calls to ensure that you manipulate the intended stack.




OpenGL Distilled
OpenGL Distilled
ISBN: 0321336798
EAN: 2147483647
Year: 2007
Pages: 123
Authors: Paul Martz

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net