4/21
1.3. Error handling
The following source code follows the same execution than the previous one: creation of an empty window, and load of OpenGL functions. But this time, it adds error handling.
[code]
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <vector>
// Function to be called when OpenGL detects an error
void APIENTRY error_opengl_callback( GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam);
int main()
{
std::cout<<"*** Init GLFW ***"<<std::endl;
const int glfw_init_value = glfwInit();
if( glfw_init_value != GLFW_TRUE ) {
std::cerr<<"Failed to Init GLFW"<<std::endl;
abort();
}
std::cout<<"*** Create window ***"<<std::endl;
const int window_width = 500;
const int window_height = 500;
const std::string title = "My Window";
GLFWwindow* window = glfwCreateWindow(window_width, window_height, title.c_str(), /*monitor*/ nullptr, /*share*/ nullptr);
if( window==nullptr ) {
std::cerr<<"Failed to create GLFW Window"<<std::endl;
abort();
}
glfwMakeContextCurrent(window);
std::cout<<"*** Init GLAD ***"<<std::endl;
const int glad_init_value = gladLoadGL();
if( glad_init_value == 0 ) {
std::cerr<<"Failed to Init GLAD"<<std::endl;
abort();
}
std::cout<<"*** Set OpenGL error callback ***"<<std::endl;
glEnable ( GL_DEBUG_OUTPUT );
glDebugMessageCallback( (GLDEBUGPROC) error_opengl_callback, 0 );
glDebugMessageControl ( GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, true );
std::cout<<"OpenGL information: VENDOR : "<<glGetString(GL_VENDOR)<<std::endl;
std::cout<<" RENDERDER : "<<glGetString(GL_RENDERER)<<std::endl;
std::cout<<" VERSION : "<<glGetString(GL_VERSION)<<std::endl;
std::cout<<" GLSL VERSION: "<<glGetString(GL_SHADING_LANGUAGE_VERSION)<<std::endl;
std::cout<<"*** Start GLFW loop ***"<<std::endl;
while( !glfwWindowShouldClose(window) ) {
glfwSwapBuffers(window);
glfwPollEvents();
}
std::cout<<"*** Terminate GLFW loop ***"<<std::endl;
glfwTerminate();
return 0;
}
// Function to be called when OpenGL detects an error
// See https://www.khronos.org/opengl/wiki/Debug_Output
void APIENTRY error_opengl_callback( GLenum /*source*/,
GLenum /*type*/,
GLuint /*id*/,
GLenum severity,
GLsizei /*length*/,
const GLchar* message,
const void* /*userParam*/ )
{
if( severity != GL_DEBUG_SEVERITY_NOTIFICATION ) {
// Print all error messages which are not notification
std::cerr << "\n**** Error OpenGL Callback **** \n " << message;
}
}
Error handling makes the code less short, but, as a good practice, should always be performed. Modifying your code, or executing it on other platforms, may lead to erroneous behaviors that will be far easier to debug when careful error checking is performed. Note that OpenGL based code is notably hard to debug, thus careful error checking is even more essential than for general code.
The first three functions needing error handling are respectively
-
glfwInit to make sure that GLFW library is well initialized,
-
glfwCreateWindow, to make sure that GLFW is able to create the window in this step, and
-
gladLoadGL, to check that OpenGL functions can be used afterward.
The following block of code
std::cout<<"OpenGL information: VENDOR : "<<glGetString(GL_VENDOR)<<std::endl;
std::cout<<" RENDERDER : "<<glGetString(GL_RENDERER)<<std::endl;
std::cout<<" VERSION : "<<glGetString(GL_VERSION)<<std::endl;
std::cout<<" GLSL VERSION: "<<glGetString(GL_SHADING_LANGUAGE_VERSION)<<std::endl;
prints on the command line different information about the OpenGL capability of your system (see glGetString), typically the vendor, type of graphics card, and the version of OpenGL that your system can handle. Note that these information is dependent of your hardware and driver (native or open-source driver may handle different version of OpenGL). Note also that you may run any OpenGL version which is less or equals to the one indicated by glGetString(GL_VERSION).
OpenGL Debug Output
The following block of code
glEnable ( GL_DEBUG_OUTPUT );
glDebugMessageCallback( (GLDEBUGPROC) error_opengl_callback, 0 );
glDebugMessageControl ( GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, true );
relates to recent OpenGL error handling [1].
The OpenGL Debug Output system allows to automatically call a specific user defined function when an OpenGL error is detected.
-
glEnable( GL_DEBUG_OUTPUT );_ activate the OpenGL Debug Output functionality
-
glDebugMessageCallback( functionName, 0 ); set up the Callback Function, i.e. the user defined function that will be called when the error is detected.
-
glDebugMessageControl ( … ) setup types of errors that will be captured by the callback system.
Finally, the user defined function error_opengl_callback display the OpenGL error message when the associated severity is greater than a simple notification [2].