glsIntro(3G) OpenGL Stream Codec glsIntro(3G)
glsIntro - Introduction to the OpenGL Stream Codec
The OpenGL Stream Codec (GLS) is a facility for encoding and decoding
streams of 8-bit bytes that represent sequences of OpenGL (henceforth,
"GL") commands.
The GLS specification has two components:
1. A set of three byte-stream encodings for GL and GLS commands:
human-readable text, big-endian binary, and little-endian binary.
The three encodings are semantically identical; they differ only in
syntax. It is therefore possible to convert GLS byte streams freely
among the three encodings without loss of information.
2. An API that provides commands for encoding and decoding GLS byte
streams. This API is not formally an extension of the GL API. Like
the GLU API, the GLS API is designed to be implemented in an
optional, standalone client-side subroutine library that is separate
from the subroutine library that implements the GL API.
The GLS encodings and API are platform independent and window system
independent. In particular, the GLS encodings are not tied to the X
Window System protocol encoding used by the GLX extension. GLS is
designed to work equally well in UNIX, Windows, and other environments.
GLS can be used in a variety of situations, for example:
* GL command streams for resolution-independent storage, interchange,
viewing, and printing of pictures
* GL command files for persistent storage of textures, display lists,
images, and so on
* GL trace streams for debuggers, performance analyzers, and
simulators
* GL test-vector streams that test correctness of GL implementations
* Transfer of GL commands between application processes via bytestream
connections
* Client-side display lists that can contain client callbacks
Some of these applications require the definition and implementation of
higher-level APIs that are more convenient to use than the GLS API. The
GLS API design is an attempt to provide basic encoding and decoding
services in such a way that higher-level services can efficiently be
built on top of it.
Page 1
glsIntro(3G) OpenGL Stream Codec glsIntro(3G)
GLS Encodings [Toc] [Back]
Each of the GLS encodings (human-readable text, big-endian binary, and
little-endian binary) can represent all GL commands, without exception.
This includes "get" commands that return data to the GL client and other
commands that are not allowed in GL display lists.
If a GL command has both a scalar form (for example glColor3f()) and a
vector form (for example, glColor3fv()), GLS always represents the
command in its vector form.
In addition to GL commands, a subset of the commands in the GLS API are
"encodable", that is, they can be represented in GLS streams. These GLS
commands make it possible to encode various kinds of non-GL data in GLS
streams.
The binary encodings represent most commands as 16 bits of opcode,
followed by 16 bits of byte-count, followed by zero or more 32-bit words
of argument data. An alternate encoding is used for opcodes larger than
65535 and commands that require more than 65535 bytes to encode.
The text encoding looks like C source code, except that array arguments
are represented as lists of elements delimited by braces. Enumerants are
represented symbolically. Here's an example of a GLS text stream:
glsBeginGLS(1, 0); # arguments are major, minor GLS version
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glBegin(GL_POINTS);
glVertex3fv({1.2, 3.4, 5.6});
glEnd();
glsEndGLS();
All GLS streams begin with the encodable GLS command glsBeginGLS() and
end with the encodable GLS command glsEndGLS(). The concatenation of two
valid GLS streams is always a valid GLS stream, even if the two streams
do not have the same GLS encoding.
GLS API [Toc] [Back]
This section provides a brief overview of the core of the GLS API. It
consists of three subsections: "Working with Contexts", "Basic Stream
Capture" "Basic Stream and Playback", and "Modifying Stream Capture and
Playback".
Working with Contexts
Like GL, GLS defines a state machine. A GLS context is an instantiation
of this state machine. GLS contexts and GL contexts are completely
independent. GLS contexts are stored entirely on the client side of the
GL client-server connection. Each GLS context has a nonzero name of type
GLint.
Page 2
glsIntro(3G) OpenGL Stream Codec glsIntro(3G)
Each GLS command is classified as either global, immediate, or encodable.
All immediate and encodable commands use the GLS context state.
The commands glsGenContext(), glsDeleteContext(), and glsContext() (see
below) are global. All other GLS commands described on this page are
non-global. Each client thread has a state variable that always contains
either zero (the initial value) or the name of the thread's current GLS
context.
* If the value is zero, all non-global GLS commands are no-ops, and
non-global GLS commands that return a value return zero.
* If the value is nonzero, all non-global GLS commands use the state
in the issuing thread's current GLS context.
At any given instant, a GLS context may be current to at most one thread.
The following functions are available for working with contexts:
GLint glsGenContext(void);
void glsDeleteContext(GLint inContext);
void glsContext(GLint inContext); /* set thread's current GLS context */
Basic Stream Capture
For basic stream capture, call glsBeginCapture().
Between a glsBeginCapture() command and the following glsEndCapture()
command, the current GLS context is in capture mode. In capture mode,
all commands are captured instead of executed:
* All GL commands are captured by GLS instead of being sent directly
to GL and executed.
* All encodable GLS commands are captured instead of being sent
directly to GLS and executed.
The command glsBeginCapture() opens a stream for writing and then encodes
the command glsBeginGLS(). The command glsEndCapture() encodes the
command glsEndGLS() and then closes the currently open GLS stream.
glsBeginCapture() and glsEndCapture() have the following prototypes:
GLboolean glsBeginCapture(
const GLSchar *inStreamName,
GLSenum inStreamType,
GLint inWriteFlags
);
void glsEndCapture(void);
The inStreamType argument to glsBeginCapture() is one of:
Page 3
glsIntro(3G) OpenGL Stream Codec glsIntro(3G)
GLS_CONTEXT /* in-memory stream stored in GLS context */
GLS_BINARY_LSB_FIRST /* binary stream, little-endian */
GLS_BINARY_MSB_FIRST /* binary stream, big-endian */
GLS_TEXT /* text stream */
The inWriteFlags argument to glsBeginCapture() is a mask. Zero or more
attributes can be OR'ed together to set various options:
GLS_WRITE_APPEND_BIT /* if stream exists, don't truncate */
GLS_WRITE_BARE_BIT /* don't encode glsBeginGLS/glsEndGLS */
Here's how the different values for inStreamType affect the capture
process:
* If inStreamType is GLS_CONTEXT, glsBeginCapture() opens an in-memory
stream named inStreamName that is stored in the current GLS context.
Within the constraints of available memory, a GLS context can
contain an arbitrary number of named GLS_CONTEXT streams.
GLS_CONTEXT streams can be thought of as client-side display lists
that complement the server-side display lists provided by core GL.
* If inStreamType is GLS_BINARY_LSB_FIRST, GLS_BINARY_MSB_FIRST, or
GLS_TEXT, the name of the opened stream is formed by appending
inStreamName to a write-prefix string that is stored in the current
GLS context.
Use glsWritePrefix() to replace the value of the write-prefix
string. See "Modifying Stream Capture and Playback" below.
* If inStreamType is GLS_BINARY_LSB_FIRST, GLS_BINARY_MSB_FIRST, or
GLS_TEXT, and inStreamName is not the empty string (""), the command
glsBeginCapture() uses the standard C library command fopen() to
create a write channel of type FILE*.
* If inStreamType is GLS_BINARY_LSB_FIRST, GLS_BINARY_MSB_FIRST, or
GLS_TEXT, and inStreamName is the empty string, and the GLS client
has used the command glsWriteFunc() specify a write callback
function, that function is used in place of the standard C library
function fwrite() to write bytes to the stream.
* If inStreamType is GLS_BINARY_LSB_FIRST, GLS_BINARY_MSB_FIRST, or
GLS_TEXT, and inStreamName is the empty string, and if
glsWriteFunc() is not defined, glsBeginCapture() uses a default
write channel of type FILE* that is stored in the current GLS
context (initial value: stdout).
In that case, use glsChannel() to replace the value of the default
write channel. See "Modifying Stream Capture and Playback" below.
Basic Stream Playback
Page 4
glsIntro(3G) OpenGL Stream Codec glsIntro(3G)
glsCallStream() decodes a named GLS stream (which may be in any GLS
encoding) and issues the commands in the stream to GL and GLS, just as if
those commands had been issued directly in immediate mode by the calling
thread. The command returns the type of the stream.
GLSenum glsCallStream(const GLSchar *inStreamName);
What happens when you call glsCallStream() depends on the value of
inStreamName and other factors:
* If inStreamName is the name of a GLS_CONTEXT in-memory stream stored
in the current GLS context, glsCallStream() decodes that stream.
Otherwise, the command searches for an external stream to decode.
* If inStreamName is not the empty string (""), a sequence of
potential external stream names is formed. The first names in the
sequence are formed by appending inStreamName to each of the strings
in a list of read-prefix strings that is stored in the current GLS
context. The last name in the sequence is formed by appending
inStreamName to the write-prefix string.
Use the commands glsAppendReadPrefix() and glsPrependReadPrefix() to
modify the contents of the read-prefix string list. See "Modifying
Stream Capture and Playback" for more information.
Beginning with the first potential external stream name,
glsCallStream() tries each successive name until either a readable
stream is found or all of the names have been tried. For each name,
the command fopen() is issued with the name as an argument, in an
attempt to create a read channel of type FILE*.
* If inStreamName is the empty string, the command glsCallStream()
uses a default read channel of type FILE* that is stored in the
current GLS context (initial value: stdin). Use command glsChannel()
(see "Modifying Capture and Playback") to replace the value of the
default read channel.
* If inStreamName is the empty string, and the GLS client has used the
command glsReadFunc() to specify a read callback function, that
function is used in place of the standard C library function fread()
when bytes are to be read from the stream.
The command glsCallStream() is encodable. When a GLS decoder reads this
command from a GLS stream, the decoder recursively decodes the GLS stream
named in the command. As a result, GLS streams provide the same
embedding capability on the client side that GL display lists provide on
the server side.
Modifying Capture and Playback [Toc] [Back]
You can modify stream capture and playback in several ways, all discussed
in more detail below:
Page 5
glsIntro(3G) OpenGL Stream Codec glsIntro(3G)
* Call glsCaptureFlags() to specify the destination of a command.
* Call glsCommandFunc() to register a callback function.
* Call glsAppendReadPrefix() or glsPrependReadPrefix() to modify the
read prefix string list.
* Call glsWritePrefix() to replace the value of the write prefix
string.
* Call glsChannel() to replace the value of the default write channel
glsCaptureFlags() allows a GLS client to specify on a per-opcode basis
whether a captured GL or encodable GLS command is written to the open
stream and/or executed by GL or GLS.
void glsCaptureFlags(GLSopcode inOpcode, GLint inFlags);
A GLS context contains the following capture-mode control bits for each
opcode, set with the inFlags parameter:
GLS_CAPTURE_WRITE_BIT /* write command to open stream */
GLS_CAPTURE_EXECUTE_BIT /* execute command */
glsCommandFunc() registers the client callback function inFunc for the GL
or encodable GLS command designated by inOpcode. There are two types of
callback function: GLS_CALL_FUNC and GLS_CAPTURE_FUNC. The parameter
inAttrib identifies the type of function to be registered.
When a GLS decoder reads a command from a GLS stream, and a GLS_CALL_FUNC
function has been registered for that command, the decoder calls that
function instead of issuing the command.
When GLS captures a command, and a GLS_CAPTURE_FUNC function has been
registered for that command, GLS calls that function instead of the
standard GLS capture function for that command. If desired, the callback
function may call the standard GLS capture function, which is named
GLScapture_<commandname>.
void glsCommandFunc(GLSenum inAttrib, GLSopcode inOpcode, GLScommandFunc inFunc);
Command arguments are passed to inFunc just as they be passed to the
function that implements the GL or GLS command. The function inFunc is
free to perform arbitrary computations, including issuing GL and GLS
commands.
Certain encodable GLS commands are provided for the sole purpose of
encoding arrays of arbitrary client data as command arguments in a GLS
stream. If a GLS client provides a callback function for one or more of
these encodable GLS commands, the client can use GLS_CONTEXT in-memory
streams to create client-side display lists that contain client
callbacks. This functionality is available in IrisGL but not in core GL.
Page 6
glsIntro(3G) OpenGL Stream Codec glsIntro(3G)
void glsUnsupportedCommand(const GLSchar *inCommand);
The GLS encodings and API are designed to handle GL extensions.
Extension commands are encoded and decoded in the same way as GL 1.0
commands. Extension opcodes for the binary encodings will be allocated
on demand in blocks of 16 from a registry maintained by Silicon Graphics.
To guarantee successful interchange of GLS streams, any GLS
implementation has to be able to read any GLS stream, even if that stream
contains extension commands that are not recognized by that GLS
implementation.
If a GLS decoder reads a command that it cannot decode from a GLS stream,
the decoder issues the encodable GLS command glsUnsupportedCommand().
Use glsCommandFunc() to register a client callback function for the
command glsUnsupportedCommand().
glsWritePrefix() lets you replace the value of the write prefix string.
The function has the following prototype:
void glsWritePrefix (const GLSchar *inPrefix);
The write prefix string is appended to inStreamName by glsBeginCapture().
Here's an example of using glsWritePrefix(). This example captures into
the file "/usr/tmp/foo.gls
glsWritePrefix("/usr/tmp/");
glsBeginCapture("foo.gls");
glBegin(GL_POINTS);
glVertex3f(1., 2., 3.);
glEnd();
glsEndCapture();
glsAppendReadPrefix() and glsPrependReadPrefix() can be used to change
the name given to glsCallStream(). They have the following prototypes:
void glsPrependReadPrefix (const GLSchar *inPrefix)
void glsAppendReadPrefix (const GLSchar *inPrefix)
Here's an example that calls the stream /usr/tmp/foo.gls:
glsAppendReadPrefix("/tmp/"); glsAppendReadPrefix("/usr/tmp/");
glsCallStream("foo.gls");
The GLS API and encodings are subject to change during the OpenGL ARB
multivendor standardization process for GLS, which is not yet complete.
Due to the multivendor standardization process, the GLS API and binary
stream encodings that are supported in this release are NOT compatible
with the GLS API and binary stream encodings that were supported in IRIX
6.2.
Page 7
glsIntro(3G) OpenGL Stream Codec glsIntro(3G)
The GLS text stream encoding supported in this release is compatible with
the GLS text stream encoding that was supported in IRIX 6.2. To convert
an IRIX 6.2 GLS binary stream to the new format, use the utility
/usr/sbin/glscat on an IRIX 6.2 system to convert to text format, then
use the version of /usr/sbin/glscat in the current release to convert
back to binary format:
irix6.2> /usr/sbin/glscat -t t < inStream > outStream
irix6.X> /usr/sbin/glscat -t b < inStream > outStream
IRIX 6.2 applications that use GLS must be recompiled to run with the new
version of GLS. Note that the new parameter inAttrib has been added to
the command glsCommandFunc. For existing code, the value of inAttrib
should be GLS_CALL_FUNC.
PPPPaaaaggggeeee 8888 [ Back ]
|