blob: 967d2b5bbecddc086f04ec7831459661ed5940b8 [file] [log] [blame]
Name Strings
Jack Middleton, Sun (Jack.Middleton 'at'
$Date: 1999/12/28 01:40:37 $ $Revision: 1.4 $
SUN Date: 99/06/25 13:12:54 Revision: 1.6
OpenGL 1.1 is required
OpenGL has two chained triangle primitives, TRIANGLE_STRIP and
TRIANGLE_FAN. For multiple, consecutive triangle strips or
triangle fans, the overhead of Begin and End, or separate calls to
DrawArrays, can be significant depending on the number of triangles
per strip or fan.
Many surface tessellators produce triangle strips with very few
triangles per strip before needing to restart a new strip. Even
sophisticated tessellators typically need to restart a new strip,
or switch from a triangle strip to a triangle fan, many times
within a single object. Such tessellators can often produce a more
efficient tessellation--one with fewer vertices--by mixing strips
and fans within the same object. The ability to switch from one to
the other without restarting the strip or fan yields even more
savings. Unfortunately, the overhead of switching from a triangle
strip to a triangle fan, or vice versa, can reduce, or even
eliminate the benefit gained from reducing the number of vertices.
A new triangle list primitive, along with an associated replacement
code attribute, is defined by this extension to allow multiple
triangle strips and fans to be specified within the same Begin/End
pair or from a single call to DrawArrays. The triangle list
extension also provides the means to switch between triangle strips
and triangle fans with or without restarting the strip or fan.
TRIANGLE_LIST is a new primitive type (i.e., new Begin mode) that
uses the ReplacementCodeSUN state attribute to determine whether the
current vertex replaces the oldest vertex, as in a triangle strip,
the middle vertex, as in a triangle fan, or restarts a new chained
triangle list. The first vertex of a new triangle list is
implicitly treated as a RESTART. The first three vertices complete
the first triangle, after which the replacement codes of the vertex
are used. The two vertices immediately following a
restart--including the implicit restart on the first vertex--are
ignored. The ReplacementCodeSUN attribute is part of the vertex
state, and is only used by the TRIANGLE_LIST primitive.
1. Two types of restarts: CW/CCW
Compressed geometry supports the notion of RESTART_CW versus
RESTART_CCW. These two types of restart are supported by all
of Sun's hardware and this capability was exposed via XGL. We
need to decide whether we want to expose this in OpenGL. In a
sense, we already have exposed it with the compressed geometry
extension, since the compressed geometry spec allows both types
of restart.
It is worth noting that these modes are somewhat misnamed.
They really don't override the meaning of the GL_FRONT_FACE
flag (nor did they override the equivalent XGL mode, either).
Rather, the type of restart either inverts the GL_FRONT_FACE
state, in the case of RESTART_CW, or it uses the GL_FRONT_FACE
flag unmodified, in the case of RESTART_CCW. This should be
the case for compressed geometry today (although it may be
broken), and it would be true for triangle lists if we decided
to expose this capability. My preference would be to not
expose this, since all it really does is create a documentation
headache. The user can always define a generalized triangle list
with consistently wound triangles using the CCW variant of restart.
Supporting both types of restart just doesn't fit into OpenGL's
(or Java 3D's) model cleanly.
[NOTE: a decision has been made to not expose the CW/CCW feature]
2. Enumerated values for replacement codes
Enumerated values used for extensions are typically defined as
integers in a specified range. This range depends on whether
they are vendor private (_SUN) or multi-vendor (_EXT or _ARB)
extensions. For this extension, we are defining a new
replacement code attribute that is part of the vertex state
and is expected to be processed directly by hardware. Given
this, we have defined the replacement codes as small integer
values (1, 2, and 3) that correspond with what the hardware
wants to see. The cost for having these values be different,
especially for replacement codes in a vertex array, are too
Another reason for not using constants in the range of
extension enums is that if this ever became part of the core
after first being an extension, or even if it became a
multi-vendor extension after first being a Sun-private
extension, then the codes would change. This would be
unworkable for an attribute such as this, since it is part of
the vertex pipeline.
We need to ensure that our current plan of defining
replacement codes outside the range of extension enums is not
violating any rules. I think that this shouldn't be a problem
since the replacement codes themselves are really just
parameters to the replacement code command. As such, they are
just bit patterns and shouldn't need to be unique.
New Procedures and Functions
void ReplacementCodeuiSUN(uint code);
void ReplacementCodeusSUN(ushort code);
void ReplacementCodeubSUN(ubyte code);
void ReplacementCodeuivSUN(const uint *code);
void ReplacementCodeusvSUN(const ushort *code);
void ReplacementCodeubvSUN(const ubyte *code);
void ReplacementCodePointerSUN(enum type,
sizei stride,
const void *pointer);
New Tokens
Accepted by the <mode> parameter of Begin, DrawArrays,
DrawElements, MultiDrawArraysSUN, MultiDrawArraysEXT,
MultiDrawElementsSUN, and MultiDrawElementsEXT:
Accepted by the by the <pname> parameter of GetBooleanv,
GetIntegerv, GetFloatv, and GetDoublev:
Accepted by the <code> parameter of ReplacementCode{ui,us,ub}[v]SUN:
Accepted by the <array> parameter of EnableClientState and
DisableClientState, and by the <cap> parameter of IsEnabled:
Accepted by the <pname> parameter of GetBooleanv, GetIntegerv,
GetFloatv, and GetDoublev:
Accepted by the <pname> parameter of GetPointerv:
Accepted by the <format> parameter of InterleavedArrays:
R1UI_V3F_SUN 0x85C4
R1UI_C4UB_V3F_SUN 0x85C5
R1UI_C3F_V3F_SUN 0x85C6
R1UI_N3F_V3F_SUN 0x85C7
R1UI_C4F_N3F_V3F_SUN 0x85C8
R1UI_T2F_V3F_SUN 0x85C9
Additions to Chapter 2 of the GL Specification (OpenGL Operation)
Replacement Code
The replacement code is a per-vertex state attribute that controls
triangle vertex replacement for the triangle list primitive; it is
ignored for all other primitives. This state attribute is set by
the ReplacementCodeSUN command. Since it is part of the vertex state,
the ReplacementCodeSUN command may appear within a Begin/End pair. The
replacement code is an enum with 3 values, RESTART_SUN,
Note that the replacement code follows the same rules as other
per-vertex state attributes. The current value of the replacement
code state attribute affects subsequent vertices until the next
time the ReplacementCodeSUN command is executed, updating the value
of the state attribute. This means that a replacement code that is
set outside of a Begin/End will affect subsequent triangle lists in
which the replacement code is not set. Similarly, the value of the
last replacement code set within a Begin/End will affect subsequent
triangle lists in which the replacement code is not set.
Triangle List
A triangle list primitive is a series of triangles that are
connected according to the replacement codes associated with each
vertex in the list. A triangle list is specified by giving a
series of defining vertices between a Begin/End pair when Begin is
called with TRIANGLE_LIST. As with a triangle strip and a triangle
fan, the first three vertices define a triangle. The order of the
three vertices is significant. Subsequent vertices either define a
triangle that is connected to the previous triangle using the new
vertex and two vertices from the previous triangle, or they restart
a new triangle, depending on the value specified by the replacement
code state. The edge flag attribute is ignored by the triangle list
primitive. If PolygonMode is set to LINE or POINT, then all edges
or vertices are drawn (as with TRIANGLE_STRIP and TRIANGLE_FAN).
In addition to the current vertex, the state required to support
triangle lists consists of a 2-bit vertex counter that indicates
the number of vertices since the beginning of the list or since a
restart, two stored processed vertices, and a one-bit pointer
indicating the order of drawing (oldest-middle-current versus
The rules for determining when to draw a triangle and what vertices
to use and in what order are as follows:
1. When a BEGIN command is called with TRIANGLE_LIST, the vertex
counter is set to 0.
2. When a new vertex is completed, the following logic is used to
process the vertex:
if (vertex_counter == 0) {
vertex_counter = 1
drawing_order = 0
vertexA = currentVertex
else if (vertex_counter == 1) {
vertex_counter = 2
vertexB = currentVertex
else if (vertex_counter == 2) {
vertex_counter = 3
draw(vertexA, vertexB, currentVertex)
else {
if (repl_code == RESTART) {
vertex_counter = 1
drawing_order = 0
vertexA = currentVertex
else {
if (repl_code == REPLACE_OLDEST)
drawing_order = !drawing_order
if (drawing_order == 0)
draw(vertexA, vertexB, currentVertex)
draw(vertexB, vertexA, currentVertex)
if (repl_code == REPLACE_OLDEST)
vertexA = vertexB
vertexB = currentVertex
If a triangle list has fewer than 3 vertices then no triangles are
drawn. If a triangle list has fewer than 2 vertices following a
vertex with a RESTART replacement code, then the restart is
ignored, along with the one vertex after the restart, if present.
Because the replacement code is ignored for the first vertex and
the two vertices immediately following a restart, a constant
replacement code has a well-defined, consistent semantic. If the
replacement code for each vertex is REPLACE_OLDEST, then a triangle
strip will be drawn. If the replacement code for each vertex is
REPLACE_MIDDLE, then a triangle fan will be drawn. If the
replacement code for each vertex is RESTART, then isolated
triangles will be drawn.
The following example illustrates the use of vertex replacement
within a single triangle list to draw triangle strips, triangle
fans, isolated triangles, and, finally, a triangle strip that
switches to a fan and back to a strip without a restart. In this
example REPLACE_OLDEST is abbreviated RO and REPLACE_MIDDLE is
abbreviated RM. Note that the initial RESTART replacement appears
in square brackets, indicating that it is an implicit restart; the
replacement code is ignored for the first vertex following a begin
command. The replacement code is also ignored for the two
vertices immediately following a restart.
2 4 6
V1 [RESTART] .-------.-------.
V2 -- /\ /\ /
V3 -- / \ / \ /
V4 RO / \ / \ / Triangle Strip
V5 RO / \/ \/
V6 RO .-------.-------.
1 3 5
/\ /\
V7 RESTART / \ / \
V8 -- / \ / \
V9 -- / \/ \
V10 RM 8.------.7-------.11 Triangle Fan
V11 RM 14\ /\ /
V12 RM \ / \ /
V13 RM \ / \ /
V14 RM \/ \/
13 12
16 19
V16 -- /\ /\
V17 -- / \ / \
V18 RESTART / \ / \ Isolated Triangles
V19 -- / \ / \
V20 -- .--------. .--------.
15 17 18 20
22 24 26
V21 RESTART |\ |\ |\
V22 -- | \ | \ | \
V23 -- | \ | \ | .27
V24 RO | \ | \ | /\
V25 RO | \| 25/ \
V26 RO .-----.-----.---.28 Mixed Strip & Fan
V27 RO 21 23 /|\ |
V28 RM / | \ |
V29 RM / | \|
V30 RM .---.---.29
V31 RM 31\ /30
V32 RO \ /
Triangle list primitives may be drawn using vertex arrays in the
same manner as other primitives. The replacement code state flag
may be enabled as part of a vertex array operation. The
REPLACEMENT_CODE_ARRAY_SUN enum is used to enable or disable the
replacement code array using the EnableClientState and
DisableClientState functions.
The following function defines the type, stride, and pointer for
the replacement code data.
void ReplacementCodePointerSUN(enum type,
sizei stride,
const void *pointer);
Legal values for type are UNSIGNED_BYTE, UNSIGNED_SHORT, and
UNSIGNED_INT. As with other vertex state, the value of the
replacement code attribute is undefined after a vertex array
command has been executed.
The following describes the memory layout of the new interleaved
array types. These new types may be used as the format parameter
of the InterleavedArrays function.
format pt pc pn pv s
--------------------- ------ ------ ------ ------ ------
R1UI_V3F i i+3f
R1UI_C4UB_V3F i i+c i+c+3f
R1UI_C3F_V3F i i+3f i+6f
R1UI_N3F_V3F i i+3f i+6f
R1UI_C4F_N3F_V3F i i+4f i+7f i+10f
R1UI_T2F_V3F i i+2f i+5f
R1UI_T2F_N3F_V3F i i+2f i+5f i+8f
R1UI_T2F_C4F_N3F_V3F i i+2f i+6f i+9f i+12f
Where i is sizeof(UNSIGNED_INT) rounded up to the nearest multiple of
f. The replacement code pointer always starts at offset 0 from the
interleaved array pointer.
Additions to Chapter 3 of the GL Specification (Rasterization)
Additions to Chapter 4 of the GL Specification (Per-Fragment Operations
and the Framebuffer)
Additions to Chapter 5 of the GL Specification (Special Functions)
Additions to Chapter 6 of the GL Specification (State and State Requests)
Additions to the GLX / WGL / AGL Specifications
GLX Protocol
Three rendering commands are sent to the server as part of
the glXRender request:
2 8 rendering command length
2 16388 rendering command opcode
4 CARD32 code
2 8 rendering command length
2 16389 rendering command opcode
1 CARD8 code
1 CARD8 pad
2 CARD16 pad
2 8 rendering command length
2 16390 rendering command opcode
2 CARD16 code
2 CARD16 pad
INVALID_ENUM is generated if ReplacementCodePointerSUN parameter
INVALID_VALUE is generated if ReplacementCodePointerSUN parameter
<stride> is negative.
New State
Get Value Get Command Type Initial Value
--------- ----------- ---- -------------
Get Value Attribute
--------- ---------
New Implementation Dependent State
Revision History
6/25/99 Added fields from the new extension template.