mirror of
https://github.com/openharmony/third_party_opengles.git
synced 2026-07-20 21:59:30 -04:00
2725fffb4d
Signed-off-by: lizheng <lizheng2@huawei.com>
539 lines
22 KiB
HTML
539 lines
22 KiB
HTML
<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>
|