How to Create OpenGL Extensions

This document outlines the steps to create, define, and use an OpenGL, GLX, WGL, or AGL (TBD) extension. The steps include


Specification

When initially creating an extension, take the following steps:

Is there already an extension that does what I want?

Specifications for extensions that have already been developed can be obtained from the OpenGL Extension Registry maintained by SGI. The direct URL to the registry is http://oss.sgi.com/projects/ogl-sample/registry/. http://www.opengl.org/Documentation/Extensions.html.

It's possible that additional extensions may have been submitted to the registry but not yet updated on the website, or that another licensee may be working on a similar extension but not yet have released the specification.

Should the extension be multivendor, or specific to a single vendor?

If the functionality being exposed will be available from multiple licensees, it's a good idea to agree on a single extension. This makes life much easier for ISVs wanting to use this functionality, and correspondingly increases the likelihood that they will use it.

In some cases, vendors may share a common core of functionality with vendor-specific additional features. Here, it may make sense to agree on a multivendor extension to access the core, with additional vendor-specific extensions layered on the core exposing unique features.

Finally, some extensions will probably have to remain proprietary.

How do I write a specification?

Start with the template for writing extension specifications. It is important to think about all the different areas of the OpenGL (and perhaps GLX, WGL, or AGL) specification that are affected. For example, if you are defining a new attribute, can it be pushed and popped? How do you read back the values?) The template can help you with this.

Extension specifications must be written against a specific version of the OpenGL Specification. If possible, it's highly preferable to write against the most recent public version. By "written against", we mean that new language must be written as modifications to well-defined sections of the Specification. It should be possible for someone not involved with the development of an extension to sit down with a copy of the Specification and the extension and produce a merged document identical to that you intended.

Write the specification as a "lineprinter" text document: 7-bit ASCII characters with hard newlines, lines no longer than 72 character unless it's unavoidable (as when writing state table entries). Unlike HTML, proprietary wordprocessor formats, or even autoflowed text, this format will be readable on all of the immense variety of mail readers and text browsers used by OpenGL licensees and coders.

Note: we're considering creating an HTML template for specifications.

One complete, shipping example to refer to is the Fog Coordinate extension specification.

Naming Conventions

API entry points and enumerants in an extension must follow the OpenGL syntax rules. to construct names for API entry points and enumerants. In particular, follow the sections "Extension name rules" and "Shared extensions".

All extensions must be named and the name should be included in the extension specification. The extension name must have the vendor-specific acronym or EXT prepended to the front. (e.g., SGI_new_extension or EXT_new_extension). Do not choose names that are strict prefixes of existing extension names, or which are prefixed by existing extension names.

If the extension modifies OpenGL then the token GL_<ext_name> (e.g., GL_SGI_new_extension or GL_EXT_new_extension) must be included in the extension string that is returned by glGetString and it also must be defined in <GL/gl.h> (or an include file that gl.h includes, such as the glext.h header provided in the registry).

If the extension modifies GLX then the token GLX_<ext_name> (e.g., GLX_SGI_new_extension or GLX_EXT_new_extension) must be included in the extension string that is returned by glXQueryExtensionsString, glXGetClientString, and glXQueryServerString (see below for a description of the different routines). It must be defined in <GL/glx.h> (or an include file that glx.h includes, such as the glxext.h header provided in the registry).

Note that extensions can have both OpenGL components and windowing system components. For example, the SGI multisampling extension modifies both GLX and OpenGL. In this case there will be two tokens associated with the extension (e.g., GL_SGIS_multisample and GLX_SGIS_multisample) and the extension will be advertised by both OpenGL and GLX.

Extension Registry

SGI keeps a registry of enumerated type values, GLX codes (vendor private opcodes, vendor private with reply opcodes, new visual attribute type values, GLX error codes and GLX event codes), OpenGL rendering codes for GLX, and OpenGL rendering codes for GLS and extension numbers. Vendors shipping extensions using any of these values must obtain them from SGI.

If an extension defines new enumerant names, values for those names must be requested in one or more blocks of 16 values from SGI. If an extension defines new OpenGL rendering commands then you need to register GLS rendering codes for it. If you want the extensions to work with the X windowing system (i.e., with GLX), then you must request GLX opcodes and define GLX protocol for it.

There are detailed enumerant allocation policies for OpenGL and GLX enumerants. There is also a registry of WGL enumerants; SGI has custody of this registry as well, though it's best to coordinate requests for new enumerants via the ARB mailing list, because ownership of the WGL enumerant namespace is poorly defined.

All new extensions must have a number associated with them for documentation purposes. If an extension depends on another extension, the other extension must have a lower number. (Note that when an extension is deprecated, the number associated with it is not reassigned.) This number will also be assigned by SGI when you registry the extension.

Include all new enumerated values, GLX codes, and the extension number in the specification.

Once you have completed the extension, please make it available to other licensees and OpenGL clients by sending the extension specification to SGI and/or distributing it on the ARB mailing list. Once the extension is registered, SGI will include it in the public extension registry on oss.sgi.com.


Implementing and Advertising Extensions

Errors

Whenever possible, extensions should use existing errors instead of defining new error returns. For GLX, if a new protocol error is introduced, then an error number must be obtained from and registered with SGI.

Vendors may ship a single OpenGL library, containing extensions, for a variety of platforms. It is possible that some of the extension routines defined in the library may not be supported on some of the platforms. If this is the case and an application calls a routine that is not supported by the current OpenGL renderer then a GL_INVALID_OPERATION error should be returned.

Extension Availability

OpenGL extensions must be advertised in the extension string returned by glGetString. Note that in a client-server environment, this call returns the set of extensions that can be supported on the connection. GLX client libraries must send a glXClientInfo request to the server at start up time (if the client libarary is 1.1 or later) indicating the version of the client library and the OpenGL extensions that it supports. Then, when glGetString is called, the client issues a GetString request. The server intersects the set of extensions that the client supports with the set of extensions that it supports (if a glXClientInfo request was never received then the server assumes that the client supports no OpenGL extensions) and returns the result to the client. The client library then appends any client-side only extensions to the list and returns the result.

Extension names for OpenGL extensions supported in the GL client library should be #defined in <GL/gl.h>, or in a header file that gl.h includes (e.g., #define GL_SGI_new_extension). For Windows implementations, where <GL/gl.h> is not controlled by vendors, extensions should be declared in a vendor-specific header file (e.g., <GL/glSGI.h>).

GLX Extension Availability

GLX client-side extensions must be advertised in the extension string returned by glXGetClientString; server-side extensions must be advertised in the extension string returned by glXQueryServerString.

glXQueryExtensionsString returns the list of extensions that can be supported on the connection. If the server supports GLX version 1.1 or greater then the client issues a glXQueryServerString request, intersects the returned string with the set of extensions it can support and then appends any client-side only extensions to the list.

Extension names for GLX extensions recognized by the implementation should be defined in <GL/glx.h>, or a header file that glx.h includes (e.g., #define GLX_SGI_new_extension)

WGL Extension Availability

WGL initially had no mechanism for returning its own extensions string. For this reason, WGL extension names were initially advertised in the GL extensions string returned by glGetString. With the creation of a more formal WGL extension mechanism, all implementations offering WGL extensions should export the WGL_EXT_extensions_string extension, and should advertise WGL extensions in the extensions string returned by the wglGetExtensionsStringEXT interface defined by WGL_EXT_extensions_string, as well as via glGetString, for compatibility with older programs.

Extension names for WGL extensions recognized by the implementation should be defined in the generic <GL/glEXT.h> or the vendor-specific GL header.


Use of Extensions

Programmers that wish to use a particular OpenGL extension should check both compile-time defines (to ensure that the extension is supported by the library they are compiling against) and the extension string returned by glGetString (to ensure that the renderer supports the extension). For Windows, extensions usually are not defined at link time, and function pointers to extension APIs should be obtained by calling wglGetProcAddress.

For example, the following code could be used to check whether the renderer supports an OpenGL extension called GL_EXT_new_extension. This code would need to be executed after the context had been made current:


static GLboolean CheckExtension(char *extName, const char *extString)
{
    /*
     ** 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 can be in read-only memory.
     */
    char *p = (char *)extString;
    char *end;
    int extNameLen;

    extNameLen = strlen(extName);
    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;
}

const GLubyte *ext_string;
int new_ext_supported = GL_FALSE;

if (CheckExtension("GL_EXT_new_extension", glGetString(GL_EXTENSIONS)))
    new_ext_supported = GL_TRUE;

If the renderer supports the extension, then it is safe to use it at runtime. (Note that in a client-server environment, glGetString will only return the set of extensions that can be supported by the client and server.) However, compile time checks must be made to ensure that the library that you are linked against supports the extension. For example:


#ifdef GL_EXT_new_extension
    if (new_ext_supported)
	glNewExtensionEXT()
#endif

For a Windows OpenGL implementation, extensions are usually dynamically loaded from the device driver, rather than statically linked. Function pointers to extension APIs are obtained from wglGetProcAddress and use to invoke the extension. For example:


typedef void (WINAPI *PFNGLNEWEXTENSIONEXTPROC)();
PFNGLNEWEXTENSIONEXTPROC *glNewExtensionEXT = NULL;

/* Do this once, after context creation */
#ifdef GL_EXT_new_extension
    if (new_ext_supported)
	glNewExtensionEXT = (PFNGLNEWEXTENSIONEXTPROC)
	    wglGetProcAddress("glNewExtensionEXT");
#endif

/* Do this when calling the extension */
#ifdef GL_EXT_new_extension
    if (new_ext_supported)
	(*glNewExtensionEXT)();
#endif

Using GLX Extensions

Before using a GLX extension, programmers should check the compile time defines and the extension string returned by glXQueryExtensionsString. Since glXQueryExtensionsString is only available in GLX versions 1.1 and later, programmers must also check the GLX version.

The following code could be used to check whether an extension called GLX_EXT_new_extension can be used on the connection. This code would be executed after the connection had been opened and the existence of the GLX extension had been established.


    Display *dpy;
    int new_ext_supported = GL_FALSE;
    int major, minor, screen;

    if (!glXQueryVersion(dpy, &major, &minor))
	exit(1);
    screen = DefaultScreen(dpy);

#ifdef GLX_VERSION_1_1
    if (minor > 0 || major > 1)
	if (CheckExtension("GLX_EXT_new_extension",
			   glXQueryExtensionsString(dpy, screen)))
	    new_ext_supported = GL_TRUE;
#endif

If the extension is supported on the connection, then it is safe to use it at runtime. However, compile time checks must be made to ensure that the library that you are linked against supports the extension. For example:


#ifdef GLX_EXT_new_extension
    if (new_ext_supported)
	glXNewExtensionEXT(...)
#endif

Using WGL Extensions

Before using a WGL extension, check for its presence in the WGL extensions string. Note that the WGL extension string query is itself an extension; if not supported, WGL extensions are also advertised in the base GL extensions string.

Code snippet should go here


Last modified April 5, 1999 Jon Leech