Gregory Eitzmann (eitzmann++at++mariah.engr.sgi.com)
Tue, 14 Dec 1999 16:50:00 -0800 (PST)
You can find an online version of this same material -- with links
and references -- at the following URL:
http://reality.sgi.com/performer/multiple-contexts.html
Using Multiple Contexts with Performer
It is not always obvious when to use multiple contexts with Performer, nor
is it obvious what advantages and disadvantages you will find. This article
gives suggestions on when to use multiple contexts and the liabilities of
doing so.
Why Contexts?
If your graphics computer were built to run only one program at a time,
there might not be much need for even the concept of a context, which the
OpenGL Specification describes as "an encapsulation of current GL state."
When programmers use OpenGL, they specify the kind of drawing to be
performed by manipulating the mode of the graphics hardware.
Basics of OpenGL and Modes
This example shows one of the simpler modes, the line stipple, which draws
lines solid or with a pattern (such as dashes or dots). (The function
drawOneLine() is the user's private function.)
/* Draw dashed lines */
glEnable(GL_LINE_STIPPLE); // Turn on stippling
glLineStipple(1, 0x0f0f); // Set the pattern of dashes
drawOneLine(50.0, 125.0, 350.0, 125.0);
drawOneLine(50.0, 75.0, 350.0, 75.0);
/* Draw solid lines */
glDisable(GL_LINE_STIPPLE); // Turn off stippling
drawOneLine(50.0, 100.0, 350.0, 100.0);
drawOneLine(50.0, 200.0, 350.0, 200.0);
In the above example, the programmer has drawn dashed lines by enabling
stipple drawing with glEnable and glLineStipple. After the program issues
those commands (they set the line drawing mode), OpenGL will draw lines with
that pattern. After the program calls the glDisable function, OpenGL draws
all lines without that pattern.
OpenGL and State
In its description of state, the OpenGL specification specifies that some
state is maintained in the client, but most is maintained in the server.
SGI's OpenGL hardware (the server) records state in the graphics pipeline;
this makes drawing operations faster. Thus, the mode changes in the line
drawing example are sent deep into the graphics hardware as the program
issues them.
While all OpenGL hardware maintains some state (for example, pixel storage,
pixel transfer, texture), the amount of state in the hardware varies with
the features the hardware offers. Many OpenGL extensions require the
server to track state beyond the basics required in OpenGL.
(Contrast the OpenGL use of state with a stateless operation such as that
used in X11, where each drawing command requires a graphics context.)
Performer and State
Performer users know that much of the library concerns itself with graphics
state. Switching state (changing from one mode to another) incurs some
cost; thus, Performer is careful to minimize state changes in order to
maximize performance.
Some mode changes are more expensive than others. It is difficult to
characterize this in detail because graphics hardware differs greatly, and
efficiencies in changing mode are some of the decisions made during hardware
design.
So, Why Contexts?
As the OpenGL specification reads, a context is "an encapsulation of current
GL state." In order that the graphics hardware can support more than one
user at a time (here, user means a program drawing to the frame buffer), all
state must be recorded. By recording all state, a new graphics program can
start running in graphics hardware with its modes superceding those of the
previous program drawing to the frame buffer.
Usually, a different context is associated with each OpenGL window. When
programming with raw OpenGL, this is referred to as an OpenGL/X graphics
context. Performer shields its users from much of the complexity of
associating windows with contexts by providing pfWindows. Each pfWindow
usually has its own context, even if the windows are controlled from the
same program thread.
Battle of the Contexts
When a single OpenGL hardware machine has two or more active programs, it
must switch between them. The operating system chooses which program runs,
and when it switches from one to another, the o/s tells the graphics
hardware it is doing so. The graphics hardware knows it must swap context.
Mechanism for Swapping Contexts
The OpenGL graphics hardware swaps contexts in a way that is analogous to
the way an operating system swaps between processes: important things in
the outgoing process are saved away so that it can be restarted later; the
new process has its state restored so that it can run.
The switch between the two contexts takes time. The graphics pipeline must
be purged of all operations issued by the outgoing context, and all its
state recorded for later use. The amount of information needed to save and
restore state can be substantial; you can find the bulk of it in "State
Tables," section 6.2 of the OpenGL 1.2.1 Specification.
Cost of Swapping Contexts
If a single mode change is expensive, imagine changing every mode -- that is
the potential when swapping contexts. However, the expense of swapping
contexts does not stop there.
The state of the outgoing context must be recorded, usually on the host, so
the data contained in the state variables must be transferred. The state
variables include the contents of the textures, so all textures must be
saved, too (some hardware may optimize and save only modified textures).
When the outgoing context is properly saved, the incoming context must be
restored. All state variables must be restored so the graphics hardware is
again in the proper mode for drawing operations. Any textures that were
disturbed by intervening contexts must be refreshed. If the intervening
contexts had windows that clipped the incoming context's window, the
application must re-draw the frame.
The type of graphics hardware may have some bearing on the speed of the
context swap. Machines with fewer features have less to swap and may be
faster than a full-featured machine. Machines made for desktops may
optimize swap speed, where large machines intended for full-screen visual
simulation may consider swapping a low priority and focus less on swapping
than other features.
Alternative to Multiple Contexts
Still, there are times when it is convenient to be able to draw to different
sections of the screen, and multiple windows seem a good solution, were it
not for the penalty of switching between them. OpenGL has an alternative to
using multiple windows: viewports. Employed by calling glViewport(), this
function specifies that all subsequent drawing operations are directed to a
specified rectangle within the window, essentially creating a smaller
drawing region; by default, the viewport is set to the entire window.
The viewport is not a different window, nor is it a different context. It
is simply a mechanism to direct rendering to a smaller drawing region of the
window. Thus, no separate swapbuffers() function call is necessary -- the
viewport is simply part of the larger window which swaps its entire contents
at once. There is no mode-change penalty for using glViewport().
Viewports in Performer
Performer users can set up viewports, too, and the Iris Performer
Programmer's Guide describes the method for doing so. The
pfChannel::setViewport() member function (or the pfChanViewport() function
for C users) specifies the size and position of the viewport within the
output window.
When are Multiple Contexts a Good Idea?
This is a difficult question to answer -- it depends largely on your
application and the hardware on which it is running. The question is more
precisely asked, "When is drawing with multiple contexts less expensive than
drawing with a single context?"
A Contrived Example
It is not easy to come up with solid examples of this, but for the exercise,
imagine a scene with two areas:
* a large picture, expensive to draw, that changes infrequently, say once
per five seconds
* a small picture, inexpensive to draw, that changes at the frame rate of
the display
By placing both pictures in a single window and drawing them with viewport
operations, the graphics hardware must draw both small and large pictures at
the frame rate of the small picture -- even though the large picture need
not be updated. (While some graphics hardware may not erase the backbuffer
during swap, avoiding a need to draw the large picture again, that behavior
is not guaranteed in the OpenGL specification. For this example, do not
rely on that.)
In this example, it may be less expensive to occasionally draw the large
picture in a separate window, incurring the context switch. The time
required for the hardware to draw the large picture at high frame rate may
exceed the time required for the switch.
Advanced Topics
The graphics application program has a context and a window; however, these
are not the same. When a program uses Performer's pfWindow class functions,
the window and the context are associated with one another as part of
initialization and pfWindow::open (the C-language binding is pfOpenWin).
For information on how to manually bind an OpenGL context to a window, see
OpenGL on Silicon Graphics Systems.
Multiple Drawables
A single program may use more than one drawable (a window or pixmap),
represented in Performer as a pfWSDrawable. In typical OpenGL rendering,
programs use a single drawable for drawing operations and reading
operations.
By using more than one drawable, a program can switch between frame buffer
areas for drawing and reading. For example, a program might use a pixel
buffer (a pbuffer) in which to render an image; then, the program can copy
that image from that pixel buffer into texture memory (via one of the
glCopyTex functions) or directly into the frame buffer (via glCopyPixels).
Copying between two drawables that have similar visual characteristics is no
more expensive than a copy with a single drawable. Moreover, switching
between existing drawables is not nearly as severe as a context switch.
The book OpenGL on Silicon Graphics Systems describes how to use multiple
contexts from an OpenGL program; the two functions glXMakeCurrent and
glXMakeCurrentReadSGI allow a single program to attach to the read/write and
read-only contexts, respectively.
Shared Contexts
As described in "Multiple pfPipeWindows and Multiple pfPipes" in Chapter 12
(pfPipeWindows and pfPipeVideoChannels) of the IRIS Performer Programmer's
Guide, it is possible to use a single graphics context from two pfPipe
objects. The text gives instructions on how to set up the pfPipeWindows.
Drawing with X11
When you use X11 drawing (for example, XDrawRectangle), windows can share
the same context -- the context of the X server. While this is not of much
concern to users of Performer -- who principally use OpenGL drawing instead
of X11 drawing -- switching between drawing to different X11 windows that
use the same visual does not incur a context switch. However, using X11
drawing is typically slower than the 2-D drawing operations that X11
offers. Moreover, switching from an OpenGL context to drawing from the X
server has the same performance penalty as switching between two OpenGL
contexts.
In Summary
It may sometimes be useful to use multiple windows to draw different parts
of a display, but the expense of switching contexts is something to examine
carefully. Be aware of the costs of doing so, and take advantage of
viewports to minimize that time.
Gregory Eitzmann
This archive was generated by hypermail 2.0b2 on Tue Dec 14 1999 - 16:51:36 PST