How to parse gl.xml and produce your own loading library

In the previous article I emphasized the importance of not having a third-party loading library like glew because OpenGL is too complex and unpredictible. For example, if you want to implement a videogame with an average graphics and a large audience of users, probably OpenGL 2.1 is enough. At this point, you may need to load only that part of the library and make the right check of the extensions or just use the functions that have been promoted to the core of the current version. Remember that an extension is not guaranteed to be present on that version of OpenGL if it's not a core feature and this kind of extensions has been introduced after 3.0 to maintain the forward compatibility.

For instance, it's useful to check the extension GL_ARB_vertex_buffer_object only on OpenGL 1.4 (in that case you may want to use glBindBufferARB instead of glBindBuffer) but not on superior versions because it has been promoted to the core from the version 1.5 onward. The same applies to other versions of the core and extensions. If you target OpenGL 2.1, you have to be sure that the extensions tipically used by 2.1 applications have not been promoted to the latest OpenGL 4.5 version and to check the extenions on previous versions of the library, making sure to use the appropriate vendor prefix, like ARB. Even if with glew you can make this kind of check before using the loaded functions, I don't recommend it because glewInit() is going to load also parts that you don't want to use and you run the risk to understimate the importance of checking the capabilities.

Anyway, reading the OpenGL spec and add manually the required extensions is a time expensive job that you may don't have the time to do. Recently, the Khronos group has released an xml file where there is a detailed description of the extensions and the functions for every version of the library, it is also used to generate the gl.h and the glext.h header files with a script in Python. In the same way, you can program a script that parses the gl.xml file to generate your own loading library, making the appropriate check of the extensions and including only the part that you really need to load on your project. You can find the gl.xml file here:

The part of your interest may be divided into three categories: features, extensions and commands.


    <feature api="gl" name="GL_VERSION_2_1" number="2.1">
            <enum name="GL_PIXEL_PACK_BUFFER"/>
            <enum name="GL_PIXEL_UNPACK_BUFFER"/>
            <enum name="GL_PIXEL_PACK_BUFFER_BINDING"/>
            <enum name="GL_PIXEL_UNPACK_BUFFER_BINDING"/>
            <enum name="GL_FLOAT_MAT2x3"/>
            <enum name="GL_FLOAT_MAT2x4"/>
            <enum name="GL_FLOAT_MAT3x2"/>
            <enum name="GL_FLOAT_MAT3x4"/>
            <enum name="GL_FLOAT_MAT4x2"/>
            <enum name="GL_FLOAT_MAT4x3"/>
            <enum name="GL_SRGB"/>
            <enum name="GL_SRGB8"/>
            <enum name="GL_SRGB_ALPHA"/>
            <enum name="GL_SRGB8_ALPHA8"/>
            <enum name="GL_COMPRESSED_SRGB"/>
            <enum name="GL_COMPRESSED_SRGB_ALPHA"/>
            <enum name="GL_CURRENT_RASTER_SECONDARY_COLOR"/>
            <enum name="GL_SLUMINANCE_ALPHA"/>
            <enum name="GL_SLUMINANCE8_ALPHA8"/>
            <enum name="GL_SLUMINANCE"/>
            <enum name="GL_SLUMINANCE8"/>
            <enum name="GL_COMPRESSED_SLUMINANCE"/>
            <enum name="GL_COMPRESSED_SLUMINANCE_ALPHA"/>
            <command name="glUniformMatrix2x3fv"/>
            <command name="glUniformMatrix3x2fv"/>
            <command name="glUniformMatrix2x4fv"/>
            <command name="glUniformMatrix4x2fv"/>
            <command name="glUniformMatrix3x4fv"/>
            <command name="glUniformMatrix4x3fv"/>

The <feature> tag describes the OpenGL version while the <require> tag describes the requirements for that version, like enums and commands. The reported commands are only core features and not extensions. You can use these commands only on OpenGL 2.1 or superior and you don't need to check any extension to load them. As we'll see later, command names can be also extensions' aliases.


        <extension name="GL_ARB_timer_query" supported="gl|glcore">
                <enum name="GL_TIME_ELAPSED"/>
                <enum name="GL_TIMESTAMP"/>
                <command name="glQueryCounter"/>
                <command name="glGetQueryObjecti64v"/>
                <command name="glGetQueryObjectui64v"/>
        <extension name="GL_ARB_transpose_matrix" supported="gl">
                <enum name="GL_TRANSPOSE_MODELVIEW_MATRIX_ARB"/>
                <enum name="GL_TRANSPOSE_PROJECTION_MATRIX_ARB"/>
                <enum name="GL_TRANSPOSE_TEXTURE_MATRIX_ARB"/>
                <enum name="GL_TRANSPOSE_COLOR_MATRIX_ARB"/>
                <command name="glLoadTransposeMatrixfARB"/>
                <command name="glLoadTransposeMatrixdARB"/>
                <command name="glMultTransposeMatrixfARB"/>
                <command name="glMultTransposeMatrixdARB"/>

The tag <extensions> includes all the existing OpenGL extensions, listed in alphabet order. Like the features, each extension contains a group of requirements, like enums and commands. The attribute 'supported' clarifies if the extension is a common gl extension ('gl') or a core extension ('glcore'). As we already know, core extensions have been introduced from version 3.0 onward and their commands have no ARB prefix in the name. Also if the 'ARB' prefix is not present on the names, those functions are not core features and they cannot be loaded if their extension is not supported.


    <commands namespace="GL">
            <proto>void <name>glAccum</name></proto>
            <param group="AccumOp"><ptype>GLenum</ptype> <name>op</name></param>
            <param group="CoordF"><ptype>GLfloat</ptype> <name>value</name></param>
            <glx type="render" opcode="137"/>
            <proto>void <name>glAccumxOES</name></proto>
            <param><ptype>GLenum</ptype> <name>op</name></param>
            <param><ptype>GLfixed</ptype> <name>value</name></param>
            <proto>void <name>glActiveProgramEXT</name></proto>
            <param><ptype>GLuint</ptype> <name>program</name></param>
            <proto>void <name>glActiveShaderProgram</name></proto>
            <param><ptype>GLuint</ptype> <name>pipeline</name></param>
            <param><ptype>GLuint</ptype> <name>program</name></param>

The tag <commands> includes all the existing OpenGL functions, listed in alphabet order. These functions can be part of core features or extensions, as they are only details of commands included in those two categories. If a function is an extension, it may have a core alias indicated by the attribute 'alias':

            <proto>void <name>glBindBufferARB</name></proto>
            <param group="BufferTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
            <param><ptype>GLuint</ptype> <name>buffer</name></param>
            <alias name="glBindBuffer"/>

The two functions have similar names but they shares the same implementation. It means that calling glBindBuffer has the same effect of glBindBufferARB, but glBindBufferARB can be called only if the relative GL_ARB_vertex_buffer_object extension is present, while glBindBuffer only on Version 1.5. The same applies for other feature functions or extensions. You must check the OpenGL version with glGetIntegerv to load the commands listed on its relative <feature> and the extension with glGetString before loading the commands listed on its <extension> tag.