Chapter 5. Introduction to OpenGL Extensions

OpenGL extensions introduce new features and enhance performance. Some extensions provide completely new functionality; for example, the convolution extension allows you to blur or sharpen images using a filter kernel. Other extensions enhance existing functionality; for example, the fog function extension enhances the existing fog capability.

Many features initially introduced as extensions are promoted to become core features of later releases of OpenGL. When an extension is promoted in this fashion, it is documented as part of the core OpenGL 1.x API and usually will not be described in detail in this document.

Using the following topics, this chapter provides basic information about OpenGL extensions:

Determining Extension Availability

Function names and tokens for OpenGL extensions have a suffix describing the source of the extension—for example, glConvolutionFilter2DEXT() or glColorTableSGI(). The names of the extensions themselves (the extension strings) use prefixes—for example, SGI_color_table. The following is a detailed list of all suffixes and prefixes:

ARB 

Used for extensions that have been developed and adopted by the OpenGL Architecture Review Board, the standards body controlling the OpenGL API.

EXT 

Used for extensions that have been reviewed and approved by more than one OpenGL vendor.

SGI 

Used for extensions that are available across the Silicon Graphics product line, although the support for all products may not appear in the same release.Not all SGI extensions are supported on Silicon Graphics Onyx4 and Silicon Graphics Prism systems.

SGIS 

Used for extensions that are found only on a subset of Silicon Graphics platforms.

SGIX 

Used for extensions that are experimental: In future releases, the API for these extensions may change, or they may not be supported at all.

ATI 

Used for extensions that have been developed by ATI Technologies. These extensions are found only on platforms using ATI graphics processor units (GPUs), including Silicon Graphics Onyx4 and Silicon Graphics Prism graphics systems.

ATIX 

Used for experimental ATI extensions in the same fashion as SGIX.

HP, NV, etc.  

Used for extensions that were initially developed by other vendors. These extensions are included for compatibility with code ported from those vendors' platforms and are not available on all Silicon Graphics platforms.


Note: When an extension is promoted to the OpenGL core, the function names and tokens have the extension suffix removed. Unless otherwise documented, the suffixed and non-suffixed forms of the functions and tokens have exactly the same meaning and use. Extensions that are promoted typically are available in both suffixed and non-suffixed forms for backwards compatibility.


How to Check for OpenGL Extension Availability

All supported extensions have a corresponding definition in gl.h or glext.h (a companion header included by gl.h) and a token in the extensions string returned by glGetString(). For example, if the ABGR extension (EXT_abgr) is supported, it is defined in gl.h as follows:

#define GL_EXT_abgr 1

GL_EXT_abgr appears in the extensions string returned by glGetString(). Use the definitions in gl.h at compile time to determine if procedure calls corresponding to an extension exist in the library.


Note: In this document, OpenGL extensions are listed by name without the GL_ prefix. For example, the ABGR extension is listed under a section heading of “EXT_abgr”. However, when testing for the presence of an OpenGL extension in the extensions string or in the OpenGL header files, you must use the GL_ prefix. Note that extensions for the GLX and GLU APIs have names similarly prefixed by GLX_ and GL_, and you must use these prefixes when testing for run-time or compile-time support of those extensions.

Applications should do compile-time checking—for example, making sure GL_EXT_abgr is defined; and run-time checking—for example, making sure GL_EXT_abgr is in the extension string returned by glGetString().

  • Compile-time checking ensures that entry points such as new functions or new enums are supported. You cannot compile or link a program that uses a certain extension if the client-side development environment does not support it.

  • Run-time checking ensures that the extension is supported for the OpenGL server and run-time library you are using.

    Note that availability depends not only on the operating system version but also on the particular hardware you are using: even though the OpenGL library supports GL_CONVOLUTION_2D_EXT, you get an GL_INVALID_OPERATION error if you call glConvolutionFilter2DEXT() on a Silicon Graphics Prism system.

Note that libdl interface allows users to dynamically load their own shared objects as needed. Applications can use this interface, particularly the dlsym() function, to compile their application on any system, even if some of the extensions used are not supported.

Example Program: Checking for Extension Availability

In Example 5-1, the function QueryExtension() checks whether an extension is available.

Example 5-1. Checking for Extensions

main(int argc, char* argv[]) {
...
    if (!QueryExtension("GL_EXT_texture_object")) {
        fprintf(stderr, "texture_object extension not supported.\n");
        	exit(1);
    }
...
}

static GLboolean QueryExtension(char *extName)
{
    /*
    ** Search for extName in the extensions string. Use of strstr()
    ** is not sufficient because extension names can be prefixes of
    ** other extension names. Could use strtok() but the constant
    ** string returned by glGetString might be in read-only memory.
    */
    char *p;
    char *end;
    int extNameLen;   

    extNameLen = strlen(extName);
        
    p = (char *)glGetString(GL_EXTENSIONS);
    if (NULL == p) {
        return GL_FALSE;
    }

    end = p + strlen(p);   

    while (p < end) {
        int n = strcspn(p, " ");
        if ((extNameLen == n) && (strncmp(extName, p, n) == 0)) {
            return GL_TRUE;
        }
        p += (n + 1);
    }
    return GL_FALSE;
}

As an alternative to checking for each extension explicitly, you can make the following calls to determine the system and graphics driver release on which your program is running:


glGetString(
GL_RENDERER)
...
glGetString(
GL_VERSION) 

Given a list of extensions supported on that system for that release, you can usually determine whether the particular extension you need is available. For this to work on all systems, a table of different systems and the extensions supported has to be available. Some extensions have been included in patch releases; so, be careful when using this approach.

Checking for GLX Extension Availability

If you use any of the extensions to GLX, described in Chapter 6, “Resource Control Extensions”, you also need to check for GLX extension availability.

Querying for GLX extension support is similar to querying for OpenGL extension support with the following exceptions:

  • Compile-time defines are found in glx.h or glxext.h (a companion header included by glx.h).

  • Prefix the names of GLX extensions with GLX_ when testing for run-time or compile-time support, just as you must prefix the names of OpenGL extensions with GL_.

  • To get the list of supported GLX extensions, call glXQueryExtensionsString().

  • GLX versions must be 1.1 or greater (no extensions to GLX 1.0 exist).

  • All current Silicon Graphics platforms (Fuel, Tezro, InfiniteReality, InfinitePerformance, Onyx4, and Silicon Graphics Prism systems) support GLX 1.3. Most GLX extensions were promoted to the GLX 1.3 core, in some cases with minor changes in functionality. For maximum portability, applications should use the GLX 1.3 core functions and tokens instead of the extensions.

Taking these exceptions into account, adapt the process described in “How to Check for OpenGL Extension Availability”.

ARB_get_proc_address—The Dynamic Query-Function-Pointer Extension

On SGI IRIX systems, all functions defined by OpenGL and GLX extensions are exported statically from the OpenGL link library so that they may be called directly. This is also true on SGI Linux systems. However, the OpenGL application binary interface (ABI) for Linux does not guarantee that extension functions or core functions beyond the set of functions defined in OpenGL 1.2 and GLX 1.3 can be called statically on all Linux environments. This is because the OpenGL library, which defines static entry points, and the OpenGL hardware drivers, which define extensions, may come from different sources and, therefore, not always be compatible with each other. This is also true on Microsoft Windows systems.

As a result, the following applications must access extension functions and newer core functions, those beyond OpenGL 1.2 and GLX 1.3, dynamically at run time:

  • Applications written to be portable to Linux systems by other vendors

  • Applications written to be portable to Microsoft Windows systems

  • Applications originally written on Linux systems by other vendors or Microsoft Windows systems and ported to SGI Linux systems

The GLX_ARB_get_proc_address extension allows dynamic access to these functions at run time by providing the glXGetProcAddressARB() function.

The glXGetProcAddressARB() Function

Function glXGetProcAddressARB() is called with the name of another OpenGL or GLX extension function or a newer core function and has the following format:

void (*glXGetProcAddress(const GLubyte *procname))(void)

The value procname is a string such as “glIsObjectBufferATI” or “glCompressedTexImage2DARB”. If the OpenGL or GLX function corresponding to procname exists, glXGetProcAddressARB() returns a function pointer to the corresponding function. Because the signatures of extension functions differ, the type of the pointer returned by glXGetProcAddressARB() is the generic (void (*)(void)). The pointer must be mapped to an appropriate function pointer type corresponding to the extension and then used to call the extension function when required.

The standard headers GL/glext.h and GL/glxext.h define, respectively, OpenGL and GLX interfaces (formats and token values) for extensions and newer core functions. In addition to defining formats, the headers also define C typedefs for these functions to ease the process of storing return values from glXGetProcAddressARB(). The following is a consistent convention for deriving a typedef for such a function:

  1. Convert the name of the function to upper case.

  2. Prefix the result with “PFNGL” (meaning “pointer to GL function”).

  3. Suffix the result with “PROC”.

For example, consider the following extension function:

GLboolean glIsObjectBufferATI(GLuint buffer);

Its corresponding typedef in glext.h would be the following:

typedef GLboolean (*PFNGLISOBJECTBUFFERATIPROC)(GLuint buffer);

The typedef names for GLX extension functions are defined similarly, but using the prefix “PFNGLX” instead of “PFNGL”.

Example 5-2 shows how to query and use an extension function pointer. The example uses the glIsObjectBufferATI function(), which is part of the GL_ATI_vertex_array_object extension, supported on Onyx4 and Silicon Graphics Prism systems. The example assumes that the application has already checked the GL_EXTENSIONS string to confirm that the extension is supported and that all references to functions, typedefs, or tokens used by the extension are wrapped in a #ifdef GL_ATI_vertex_array_object/#endif block so that the application using this code compiles correctly on platforms not supporting the extension. For clarity, these compile- and run-time checks are not included in the example.

Example 5-2. Querying Extension Function Pointers

/* Declare global variable containing the extension function pointer */
PFNGLISOBJECTBUFFERATIPROC IsObjectBufferATI = NULL;

/* Query the function pointer */
IsObjectBufferATI = (PFNGLISOBJECTBUFFERATIPROC)
    glXGetProcAddressARB(“glIsObjectBufferATI”);

/* This should never happen if the extension is supported;
 * but sanity check anyway, for robustness. */
if (IsObjectBufferATI == NULL) {
    error(“Cannot obtain extension function pointer.”);
}

...

/* Later in the program, call the extension function as needed */
GLuint buffer = bufferID; /* A buffer ID to be queried */

/* Equivalent to calling
 *  if (glIsObjectBufferATI(buffer) == GL_TRUE) { ...
 */
if ((*IsObjectBufferATI)(buffer) == GL_TRUE) {
    /* buffer is indeed a vertex array buffer ID */
}


Note: Calling glXGetProcAddressARB() is an expensive operation. Do not call it every time an extension is to be called. Instead, query function pointers once after creating a context and cache the resulting pointers for future use.



Extension Wrapper Libraries and Portability Notes

Using the GLX_ARB_get_proc_address extension directly, as described in Example 5-2, can be tedious and intrusive on application code by causing many GL function calls to be performed indirectly through function pointers. Instead, use one of the many available open source extension wrapper libraries, which hide most of the details.

SGI does not currently recommend or support a specific wrapper library, because there are many popular libraries and they are frequently updated to keep track of new vendor and ARB-approved OpenGL extensions. Consult the the developer and support forums area of the OpenGL website, http://www.opengl.org/ (which is also a good place to look for information about many other OpenGL programming topics).

As a starting point, consider the following extension wrapper libraries:

Wrapper Library 

Website

GLEW 

(The OpenGL Extension Wrangler library)http://glew.sourceforge.net/

GLee 

(The OpenGL Easy Extension library)http://elf-stone.com/downloads.php#GLee

extglgen 

http://trenki.50free.org/extgl/

OglExt 

http://www.julius.caesar.de/oglext/

Note that most of these libraries run on Microsoft Windows as well as Linux (and sometimes other operating systems with OpenGL support as well).

Finding Information About Extensions

You can find information about the extensions through man pages, example programs, and extension specifications.

Man Pages

For the most up-to-date information on extensions, see the following man pages:

glintro 

Information about the current state of extensions on your system.

glXintro 

Information on GLX extensions.

Note that individual OpenGL man pages have a MACHINE DEPENDENCIES section that lists the systems on which certain extension functions or options are implemented.

Multisampling is supported on all current Silicon Graphics systems with the exception of Fuel, Tezro, and InfinitePerformance systems. Currently, it can be used with windows or pixel buffers of multisampling-capable visual types, but not with pixmaps.

Example Programs

All complete example programs included in this guide (though not the short code fragments) are available on IRIX systems in /usr/share/src/OpenGL if you have the ogl_dev.sw.samples subsystem installed. You can also find example programs through the Silicon Graphics Developer Toolbox, http://toolbox.sgi.com/.

Extension Specifications

Extension specifications describe extension functionality from the implementor's point of view. They are prepared to fit in with the OpenGL specification. Specification contain detailed information that goes beyond what developers usually need to know. If you need more details on any of the extensions, search for its specification in the OpenGL Extenstion Registry, http://oss.sgi.com/projects/ogl-sample/registry/.