Help end child hunger

Error Tracking in OpenGL

 
Prev: GLUT and FreeGLUT Next: Code Samples
 

There is an excellent tool for debugging both OpenGL and GLSL: gDebugger. Although not totally compatible with version 3.3, it still provides a very good job alerting us to errors in our code, allowing us to see the values of our uniforms, amongst many other features.

Anyway, back to our code. When we call a function from the OpenGL API we may be calling it incorrectly, and this is what glGetError is good for. “Incorrectly” can mean several things, for instance, the parameters are not in a valid range, or a function is being called without a proper context.

OpenGL does not detect every possible error that may occur. This is due to performance reasons. Error tracking takes its toll on performance, and error free applications would be delayed unnecessarily.

Every time an error is detected a flag is set and a numeric code is recorded. Any errors after that won’t be recorded so we need to make sure we check for errors at the most significant points in your application.

To check if an error has occurred we use the function:

	GLenum glGetError(void);

The return value can be one of the following:

  • GL_INVALID_ENUM: a function has been called with an inappropriate enum.
  • GL_INVALID_VALUE: A function has been called with a out of range numeric value.
  • GL_INVALID_OPERATION: An operation has been performed out of context, or not allowed in the current state
  • GL_INVALID_FRAMEBUFFER_OPERATION:vThe framebuffer object is not complete yet
  • GL_OUT_OF_MEMORY: well, this one is pretty obvious…

In all cases, except the last, the function produces no effect, i.e. the function is silently ignored. That is why it is so important to check for errors. In the last case, GL_OUT_OF_MEMORY, the outcome may be undefined.

When an error is checked, the flag is cleared, and it will stay so until a new error occurs.

Here are a few examples of errors:

	// causes a GL_INVALID_ENUM
	glEnable(GL_LINE);

	// causes a GL_INVALID_VALUE
	//when x >= GL_MAX_VERTEX_ATTRIBS
	glEnableVertexAttribArray(x);

	// causes a GL_INVALID_OPERATION
	// when n is negative or
	// is not a previously genererated index
	glBindBuffer(GL_ARRAY_BUFFER,n);

And here is an example of a situation that although not correct, it will not cause an error:

	glClearColor(-1.1, 1.0 1.0, 1.0);

In this latter case, OpenGL clamps the first value to zero.

Here is a routine to help finding those OpenGL errors. When this routine is called, and the error flag is set, it will display the error type and the source file name (useful when working with multiple files) and line number where the error was detected.

It will not display the line number that caused an OpenGL error, but rather the line where printOpenGLError was called. You’ll still have to find out which OpenGL call caused the error, but it helps to narrow down the search.

//-----------------------------------------------------------------
// Print for OpenGL errors
//
// Returns 1 if an OpenGL error occurred, 0 otherwise.
//

#define printOpenGLError() printOglError(__FILE__, __LINE__)

int printOglError(char *file, int line)
{

    GLenum glErr;
    int    retCode = 0;

    glErr = glGetError();
    if (glErr != GL_NO_ERROR)
    {
        printf("glError in file %s @ line %d: %s\n",
			     file, line, gluErrorString(glErr));
        retCode = 1;
    }
    return retCode;
}

 

Prev: GLUT and FreeGLUT Next: Code Samples
 

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: