| <html> | |
| <head> | |
| <title>How to Create Khronos API Extensions</title> | |
| </head> | |
| <body> | |
| <h1>How to Create Khronos API Extensions</h1> | |
| <p> This document outlines the steps to create, define, and use | |
| an extension for some of the APIs supported by Khronos. It | |
| is currently focused on OpenGL, OpenGL ES, GLX, and EGL. | |
| Some discussion of OpenVG and WGL is also included. | |
| <ul> | |
| <li><a href="#spec">Specifying</a> an extension prior to coding it. | |
| <li><a href="#implementation">Implementing</a> an extension (this | |
| discusses only aspects of the implemention visible to users - | |
| primarily determining if the extension is available and | |
| defining its interface in header files. | |
| <li><a href="#using">Using</a> an extension in an application (this | |
| discusses the mechanics of using an extension if and only if | |
| it's supported by an implementation). | |
| </ul> | |
| <p><hr> | |
| <a name="spec"></a> | |
| <h2>Specification</h2> | |
| <p> When initially creating an extension, take the following steps: | |
| <ul> | |
| <li><a href="#spec_existing">Determine if an existing extension</a> | |
| can be used, instead of writing a new one. This may involve | |
| reuse of an existing specification, or | |
| <a href="promoting.html">promotion</a> to multivendor or | |
| Khronos-approved status. In either case, coordinate this use | |
| with the vendor(s) defining and shipping the existing extension. | |
| <li>If no suitable extension already exists, determine if you can | |
| <a href="#spec_category">agree on a multivendor or Khronos | |
| extension</a>, or if the extension must be specific to a single | |
| vendor. | |
| <li>Develop and <a href="#spec_writing">write an extension | |
| specification</a>, following the <a href="#spec_naming">naming | |
| conventions</a>. | |
| <li>When you're ready to release the extension, freeze the | |
| specification and <a href="#spec_registry">add it to the | |
| registry</a> maintained by Khronos. At this time (but not | |
| before), you can obtain permanent token (enumerant) assignments. | |
| <li>When shipping an extension, make sure that its interfaces are | |
| defined in header files accessible to ISVs. If the extension is | |
| Khronos-approved, use the Khronos-provided headers. | |
| </ul> | |
| <a name="spec_existing"></a> | |
| <h3>Is there already an extension that does what I want?</h3> | |
| <p> Specifications for extensions that have already been developed can | |
| be obtained from the <a href="http://opengl.org/registry/"> Extension | |
| Registry</a> maintained by Khronos. Since we are just getting started | |
| with most of the Khronos APIs, the registry currently contains only | |
| OpenGL, GLX, and WGL extension specifications. | |
| <p> 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. So it's worth asking on the appropriate Working | |
| Group mailing list if anyone has defined related functionality already. | |
| <a name="spec_category"></a> | |
| <h3>Should the extension be Khronos-approved, multivendor, or specific | |
| to a single vendor?</h3> | |
| <p> OpenGL's history has made clear that ISVs do <b>not</b> want to deal | |
| with vendor-specific extensions if they can possibly avoid it. So if | |
| the functionality being exposed is going to be available on multiple | |
| platforms - as most will - it's a good idea to agree on a single | |
| extension with other vendors providing that functionality. This | |
| makes it easier for ISVs to justify using extensions. | |
| <p> If the functionality is well-understood, it may be appropriate to | |
| define a <b>Khronos-approved extension</b>. This is the most | |
| "blessed" category of extension; it goes through the | |
| entire standards process, and is approved by the group, but remains | |
| optional functionality. Many core features have been promoted | |
| directly from existing Khronos-approved extensions. | |
| <p> If Khronos as a whole isn't ready to deal with the extension, but | |
| other vendors are, then it should be defined as a <b>multivendor | |
| extension</b>. The interested parties can develop the specification | |
| entirely among themselves, outside the standards process; or they | |
| may be able to use Khronos Working Groups as a forum to develop the | |
| specification. | |
| <p> 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. | |
| <p> Finally, some extensions will probably have to remain proprietary. | |
| <a name="spec_writing"></a> | |
| <h3>How do I write a specification?</h3> | |
| <p> Start with the <a href="template.txt">template</a> for writing | |
| extension specifications. There are different templates for | |
| different APIs, but general comments apply: | |
| <ul> | |
| <li> It's important to think about all the different areas of the core | |
| language specification(s) that are affected. How are queries for | |
| state handled? What attribute group does new state belong in? How | |
| are existing calls modified or expanded in scope? How are existing | |
| objects affected by use of the extension? The template helps with | |
| this by at least reminding you to consider each part of the core | |
| language specification. | |
| <li> Extension specifications must be written against a specific version | |
| of the core API specification. If possible, it's highly preferable | |
| to write against the most recent public version. "Written | |
| against" means that new language must be written as | |
| well-defined modifications to the Specification being referenced. 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. | |
| <li> Extension specifications may also be specified as Docbook XML | |
| documents, although we're still using plain text for the most part. | |
| Docbook is a very powerful structural representation of documents, | |
| but we're still feeling our way into using it. Known <a | |
| href="toolchain.html">Docbook tools and editors</a> are described | |
| elsewhere. | |
| </ul> | |
| <p> One complete, shipping example to refer to is the | |
| <a href="../specs/EXT/fog_coord.txt">Fog Coordinate</a> OpenGL extension | |
| specification. | |
| <!-- (<a href="fog_coord.xml">Docbook source</a>). --> | |
| <a name="spec_naming"></a> | |
| <h3>Naming Conventions</h3> | |
| <p> API entry points and enumerants in an extension must be named | |
| according to the <a href="syntaxrules.txt">syntax rules</a> specific to | |
| that API. In particular, follow the sections "Extension name | |
| rules" and "Shared extensions". | |
| <p> All extensions must be named and the name included in the extension | |
| specification. The extension name is of the form | |
| <tt>"api_category_name"</tt> where | |
| <ul> | |
| <li> <tt>"api"</tt> identifies the API | |
| (<tt>"GL"</tt> for OpenGL and OpenGL ES; | |
| <tt>"EGL"</tt>, <tt>"GLX"</tt>, and | |
| <tt>"WGL"</tt> for the corresponding window-system | |
| abstraction APIs EGL, GLX, and WGL; <tt>"GLU"</tt> for the | |
| OpenGL Utility Library; and <tt>"OVG"</tt> for OpenVG. | |
| (<b>Note</b>: OpenMAX, OpenSL, OpenML TBD). | |
| <li> <tt>"category"</tt> identifies the extension category. | |
| For a vendor-specific extension, the category is a 2-3 letter string | |
| identifying the vendor: <tt>"NV"</tt> for NVIDIA, | |
| <tt>"ATI"</tt> for ATI, etc. For a multivendor extensions, | |
| the category is <tt>"EXT"</tt>. For Khronos-approved | |
| extensions, one of several API-specific categories is used | |
| (<tt>"ARB"</tt> for OpenGL extensions, | |
| <tt>"OES"</tt> for OpenGL ES extensions, | |
| <tt>"OML"</tt> for OpenML extensions, and so on). | |
| <li> <tt>"name"</tt> is one or more words separated by | |
| underscores, providing a short label for the extension. | |
| Conventionally the name is entirely lower-case. | |
| </ul> | |
| <p> For example, the extension name | |
| <tt>"GL_EXT_framebuffer_object"</tt> is used for a | |
| multivendor OpenGL extension adding support for framebuffer objects. | |
| <p> Choose names that are | |
| <ul> | |
| <li> Short. | |
| <li> Meaningful. | |
| <li> Not prefixes of any existing extension name (disregarding the | |
| category). For example, <tt>"GL_ARB_fog"</tt> is a prefix | |
| of <tt>"GL_EXT_fog_coord"</tt>, so should not be chosen. | |
| <li> Not prefixed by any existing extension name (again, disregarding | |
| the category). | |
| </ul> | |
| <p> The goal is for names to be clear, but not at the cost of confusion | |
| or ambiguity. | |
| <h4> Advertising Extension Names to Applications </h4> | |
| <p> Each Khronos API provides a way of describing the supported | |
| extensions at compile- and run-time. This is done by a combination | |
| of preprocessor tokens in header files, and queryable extension | |
| strings. | |
| <p> <b>OpenGL and OpenGL ES</b> #define a preprocessor token | |
| corresponding to the extension name in <tt><GL/gl.h></tt> (or | |
| an include file that <tt>gl.h</tt> includes, such as the | |
| <tt>glext.h</tt> header provided in the registry). When this token | |
| is defined, it indicates that the function prototypes and enumerant | |
| definitions required to use the extension are available at compile | |
| time. | |
| <p> If an OpenGL or OpenGL ES extension is supported at runtime, the | |
| extension name must also be included in the string returned by | |
| <tt>glGetString(GL_EXTENSIONS)</tt>. | |
| <p> <b>GLX</b> #defines a preprocessor token corresponding to the | |
| extension name in <tt><GL/glx.h></tt> (or an include file that | |
| <tt>glx.h</tt> includes, such as the <tt>glxext.h</tt> header | |
| provided in the registry). When this token is defined, it indicates | |
| that the function prototypes and enumerant definitions required to | |
| use the extension are available at compile time. | |
| <p> If a GLX extension is supported at runtime, the extension name must | |
| also be included in the strings returned by | |
| <b>glXQueryExtensionsString</b>, <b>glXGetClientString</b>, and/or | |
| <b>glXQueryServerString</b> (see below for a description of the | |
| different routines). | |
| <p> <b>WGL</b> #defines a preprocessor token corresponding to the | |
| extension name in the <tt>wglext.h</tt> header provided in the | |
| registry (the wgl.h supplied with Microsoft Windows does not | |
| #include <tt>wglext.h</tt>, or define any extensions itself). When | |
| this token is defined, it indicates that the function prototypes and | |
| enumerant definitions required to use the extension are available at | |
| compile time. | |
| <p> If a WGL extension is supported at runtime, the extension name must | |
| also be included in the string returned by | |
| <b>wglGetExtensionsStringEXT</b>. | |
| <p> <b>OpenVG</b> extension conventions are <i>To Be Determined</i>. | |
| <p> Note that extensions can have both OpenGL components and windowing | |
| system components. For example, the ARB multisampling extension | |
| modifies both GLX and OpenGL. In this case there will be two tokens | |
| associated with the extension (e.g., <tt>GL_ARB_multisample</tt> and | |
| <tt>GLX_ARB_multisample</tt>) and the extension will be advertised | |
| by both OpenGL and GLX. | |
| <a name="spec_registry"></a> | |
| <h3>Extension Registry</h3> | |
| <p> Khronos keeps a registry of extension specifications, 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 Khronos. | |
| <p> If an extension defines new OpenGL enumerant names, values for those | |
| names must be requested in one or more blocks of 16 values. 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. | |
| <p> There are detailed <a href="enums.html">enumerant allocation | |
| policies</a> for OpenGL, GLX, and WGL enumerants. | |
| <p> 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 Khronos when | |
| you register the extension. | |
| <p> Include all new enumerated values, GLX codes, and the extension | |
| number in the specification. | |
| <p> Once you have completed the extension, please make it available to | |
| other Khronos members and application developers, by submitting the | |
| extension specification to the Khronos Registrar for inclusion in | |
| the public registry. | |
| <p><hr> | |
| <a name="implementation"></a> | |
| <h2>Implementing and Advertising Extensions</h2> | |
| <h4><u>Errors</u></h4> | |
| <p> 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 Khronos. | |
| <p> 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 | |
| <tt>GL_INVALID_OPERATION</tt> error should be returned. | |
| <h4><u>OpenGL Extension Availability</u></h4> | |
| <p> OpenGL extensions must be advertised in the extension string | |
| returned by <b>glGetString</b>. 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 | |
| <b>glXClientInfo</b> 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 <b>glGetString</b> 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 | |
| <b>glXClientInfo</b> 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. | |
| <p> Extension names for all known OpenGL extensions are #defined in the | |
| <tt>glext.h</tt> header included in the registry. | |
| <h4><u>EGL Extension Availability</u></h4> | |
| <p> EGL extensions must be advertised in the extension string returned | |
| by <tt>eglQueryString(EGL_EXTENSIONS)</tt>. Extension names for all | |
| known EGL extensions are #defined in the <tt>eglext.h</tt> header | |
| included in the registry. | |
| <h4><u>GLX Extension Availability</u></h4> | |
| <p> GLX client-side extensions must be advertised in the extension | |
| string returned by <b>glXGetClientString</b>; server-side extensions | |
| must be advertised in the extension string returned by | |
| <b>glXQueryServerString</b>. | |
| <p> <b>glXQueryExtensionsString</b> returns the list of extensions that | |
| can be supported on the connection. The client then issues a | |
| <b>glXQueryServerString</b> request, intersects the returned string | |
| with the set of extensions it can support and then appends any | |
| client-side only extensions to the list. | |
| <p> Extension names for all known GLX extensions are #defined in the | |
| <tt>glxext.h</tt> header included in the registry. | |
| <h4><u>WGL Extension Availability</u></h4> | |
| <p> 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 | |
| <b>glGetString</b>. With the creation of a more formal WGL extension | |
| mechanism, all implementations offering WGL extensions should export | |
| the <tt>WGL_EXT_extensions_string</tt> extension, and should | |
| advertise WGL extensions in the extensions string returned by the | |
| <b>wglGetExtensionsStringEXT</b> interface defined by | |
| <tt>WGL_EXT_extensions_string</tt>, as well as via | |
| <b>glGetString</b>, for compatibility with older programs.</p> | |
| <p> Extension names for all known WGL extensions are #defined in the | |
| <tt>wglext.h</tt> header included in the registry. | |
| <p><hr> | |
| <a name="using"></a> | |
| <h2>Use of Extensions</h2> | |
| <h4><u>Using OpenGL Extensions</u></h4> | |
| <p> 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 <b>glGetString</b> (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 <b>wglGetProcAddress</b>. | |
| <p> For example, the following code could be used to check whether the | |
| renderer supports an OpenGL extension called | |
| <tt>GL_EXT_new_extension</tt>. This code would need to be executed | |
| after the context had been made current: | |
| <blockquote><pre><tt> | |
| 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; | |
| </tt></pre></blockquote> | |
| <p> If the renderer supports the extension, then it is safe to use it at | |
| runtime. (Note that in a client-server environment, | |
| <b>glGetString</b> 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: | |
| <blockquote><pre><tt> | |
| #ifdef GL_EXT_new_extension | |
| if (new_ext_supported) | |
| glNewExtensionEXT() | |
| #endif | |
| </tt></pre></blockquote> | |
| <p> 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 | |
| <b>wglGetProcAddress</b> and use to invoke the extension. For | |
| example: | |
| <blockquote><pre><tt> | |
| 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 | |
| </tt></pre></blockquote> | |
| <h4><u>Using EGL Extensions</u></h4> | |
| <p> Before using an EGL extension, check for the extension name in both | |
| the compile-time #defines and the extension string returned by | |
| <tt>eglGetString(EGL_EXTENSIONS)</tt>. For example, this code could | |
| be used to check whether an extension called | |
| <tt>EGL_OES_new_extension</tt> can be used. | |
| <blockquote><pre><tt> | |
| EGLDisplay dpy; // Initialized elsewhere | |
| int new_ext_supported = FALSE; | |
| if (CheckExtension("EGL_OES_new_extension", | |
| eglGetString(display, EGL_EXTENSIONS)); | |
| new_ext_supported = TRUE; | |
| #endif | |
| </tt></pre></blockquote> | |
| <p> If the extension is supported, then it is safe to use it at runtime. | |
| However, compile time checks must be made to ensure that you can | |
| call the extension. For example: | |
| <blockquote><pre><tt> | |
| #ifdef EGL_OES_new_extension | |
| if (new_ext_supported) | |
| eglNewExtensionEXT(...); | |
| #endif | |
| </tt></pre></blockquote> | |
| <h4><u>Using GLX Extensions</u></h4> | |
| <p> Before using a GLX extension, programmers should check the compile | |
| time defines and the extension string returned by | |
| <b>glXQueryExtensionsString</b>. | |
| <p> The following code could be used to check whether an extension | |
| called <tt>GLX_EXT_new_extension</tt> 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. | |
| <blockquote><pre><tt> | |
| 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 | |
| </tt></pre></blockquote> | |
| <p> 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: | |
| <blockquote><pre><tt> | |
| #ifdef GLX_EXT_new_extension | |
| if (new_ext_supported) | |
| glXNewExtensionEXT(...); | |
| #endif | |
| </tt></pre></blockquote> | |
| <h4><u>Using WGL Extensions</u></h4> | |
| <p> 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. | |
| <p> <i>Code snippet should go here</i> | |
| <p> <hr> | |
| <p> Last modified August 13, 2006 by Jon Leech | |
| </body> | |
| </html> |