232 lines
9.8 KiB
Plaintext
232 lines
9.8 KiB
Plaintext
|
|
||
|
Paula Womack
|
||
|
September 29, 1995
|
||
|
|
||
|
A. SPECIFICATION
|
||
|
|
||
|
Is there already an extension that does what I want?
|
||
|
|
||
|
The specifications for extensions that have already been
|
||
|
proposed by licensees can be obtained from sgiblab.sgi.com.
|
||
|
via ftp using the opengl_l account. (Get the tar file
|
||
|
extension_info.tar.Z.) Check out the extensions
|
||
|
here before creating your own. There may be another licensee
|
||
|
working on a similar extension.
|
||
|
|
||
|
Some of the extension specifications are also available
|
||
|
to the public on sgigate (using anonymous ftp). Look
|
||
|
in pub/opengl/extensions.
|
||
|
|
||
|
|
||
|
What is the best way to create a new extension?
|
||
|
|
||
|
The best way to create a new extension is to first write
|
||
|
a specification. A template can be found in the extension_info.tar.Z
|
||
|
file. It is important to think about all the different areas of
|
||
|
the OpenGL (and maybe GLX) 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.
|
||
|
|
||
|
syntax.rules is also included in extension_info.tar.Z. Your
|
||
|
extension should follow the OpenGL syntax guidelines.
|
||
|
|
||
|
All the new names introduced by the extension should have a
|
||
|
vendor-specific suffix appended to them. (e.g., glNewCommandSGI
|
||
|
or glXNewCommandSGI) If another licensee agrees to support the
|
||
|
extension, or if the ARB approves the extension, then the EXT
|
||
|
designation can be used.
|
||
|
|
||
|
How do I name my extension?
|
||
|
|
||
|
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)
|
||
|
|
||
|
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.h (or an
|
||
|
include file that gl.h includes).
|
||
|
|
||
|
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) and it
|
||
|
also must be defined in glx.h (or an include file that glx.h
|
||
|
includes).
|
||
|
|
||
|
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.
|
||
|
|
||
|
What else do I need to do?
|
||
|
|
||
|
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, OpenGL rendering
|
||
|
codes for gls and extension numbers.
|
||
|
|
||
|
If an extension defines new enumerated types then you need to register a block
|
||
|
of values from SGI (they are allocated in blocks of 16). If an extension
|
||
|
defines new OpenGL rendering commands then you need to register gls rendering
|
||
|
codes for it. Also, if you want the extensions to work with the X windowing
|
||
|
system (i.e., with GLX), then you need to request some GLX opcodes and define
|
||
|
GLX protocol for it.
|
||
|
|
||
|
All new extensions should 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 must also be registered
|
||
|
with SGI.
|
||
|
|
||
|
It is a good idea to include the new enumerated values, GLX codes and extension
|
||
|
number in the specification.
|
||
|
|
||
|
Once you have completed the extension, you should consider making it available
|
||
|
to other licensees by mailing it to opengl-licensees@sgi.com. SGI will then
|
||
|
include the new extension in the extension_info.tar file on sgiblab.sgi.com.
|
||
|
|
||
|
|
||
|
B. IMPLEMENTATION
|
||
|
|
||
|
Errors:
|
||
|
|
||
|
Whenever possible, extensions should use existing errors instead of defining
|
||
|
new error returns. For GLX, if a new protocol error is introduced, then a
|
||
|
error number must be 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
|
||
|
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 recognized by libGL.x must be defined in gl.h,
|
||
|
or a header file that gl.h includes (e.g., #define GL_SGI_new_extension)
|
||
|
|
||
|
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 OpenGL extensions recognized by libGL.x must be defined in
|
||
|
glx.h, or a header file that glx.h includes (e.g., #define GLX_SGI_new_extension)
|
||
|
|
||
|
|
||
|
C. USING 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 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
|
||
|
|
||
|
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.
|
||
|
|
||
|
For example, 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
|
||
|
need to 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)
|
||
|
glNewExtensionEXT(...)
|
||
|
#endif
|
||
|
|