1Name 2 3 SUN_triangle_list 4 5 6Name Strings 7 8 GL_SUN_triangle_list 9 10Contact 11 12 Jack Middleton, Sun (Jack.Middleton 'at' eng.sun.com) 13 14Status 15 16 Shipping 17 18Version 19 20 $Date: 1999/12/28 01:40:37 $ $Revision: 1.4 $ 21 SUN Date: 99/06/25 13:12:54 Revision: 1.6 22 23Number 24 25 165 26 27Dependencies 28 29 OpenGL 1.1 is required 30 31 32Overview 33 34 OpenGL has two chained triangle primitives, TRIANGLE_STRIP and 35 TRIANGLE_FAN. For multiple, consecutive triangle strips or 36 triangle fans, the overhead of Begin and End, or separate calls to 37 DrawArrays, can be significant depending on the number of triangles 38 per strip or fan. 39 40 Many surface tessellators produce triangle strips with very few 41 triangles per strip before needing to restart a new strip. Even 42 sophisticated tessellators typically need to restart a new strip, 43 or switch from a triangle strip to a triangle fan, many times 44 within a single object. Such tessellators can often produce a more 45 efficient tessellation--one with fewer vertices--by mixing strips 46 and fans within the same object. The ability to switch from one to 47 the other without restarting the strip or fan yields even more 48 savings. Unfortunately, the overhead of switching from a triangle 49 strip to a triangle fan, or vice versa, can reduce, or even 50 eliminate the benefit gained from reducing the number of vertices. 51 52 A new triangle list primitive, along with an associated replacement 53 code attribute, is defined by this extension to allow multiple 54 triangle strips and fans to be specified within the same Begin/End 55 pair or from a single call to DrawArrays. The triangle list 56 extension also provides the means to switch between triangle strips 57 and triangle fans with or without restarting the strip or fan. 58 59 TRIANGLE_LIST is a new primitive type (i.e., new Begin mode) that 60 uses the ReplacementCodeSUN state attribute to determine whether the 61 current vertex replaces the oldest vertex, as in a triangle strip, 62 the middle vertex, as in a triangle fan, or restarts a new chained 63 triangle list. The first vertex of a new triangle list is 64 implicitly treated as a RESTART. The first three vertices complete 65 the first triangle, after which the replacement codes of the vertex 66 are used. The two vertices immediately following a 67 restart--including the implicit restart on the first vertex--are 68 ignored. The ReplacementCodeSUN attribute is part of the vertex 69 state, and is only used by the TRIANGLE_LIST primitive. 70 71 72Issues 73 74 1. Two types of restarts: CW/CCW 75 76 Compressed geometry supports the notion of RESTART_CW versus 77 RESTART_CCW. These two types of restart are supported by all 78 of Sun's hardware and this capability was exposed via XGL. We 79 need to decide whether we want to expose this in OpenGL. In a 80 sense, we already have exposed it with the compressed geometry 81 extension, since the compressed geometry spec allows both types 82 of restart. 83 84 It is worth noting that these modes are somewhat misnamed. 85 They really don't override the meaning of the GL_FRONT_FACE 86 flag (nor did they override the equivalent XGL mode, either). 87 Rather, the type of restart either inverts the GL_FRONT_FACE 88 state, in the case of RESTART_CW, or it uses the GL_FRONT_FACE 89 flag unmodified, in the case of RESTART_CCW. This should be 90 the case for compressed geometry today (although it may be 91 broken), and it would be true for triangle lists if we decided 92 to expose this capability. My preference would be to not 93 expose this, since all it really does is create a documentation 94 headache. The user can always define a generalized triangle list 95 with consistently wound triangles using the CCW variant of restart. 96 Supporting both types of restart just doesn't fit into OpenGL's 97 (or Java 3D's) model cleanly. 98 99 [NOTE: a decision has been made to not expose the CW/CCW feature] 100 101 2. Enumerated values for replacement codes 102 103 Enumerated values used for extensions are typically defined as 104 integers in a specified range. This range depends on whether 105 they are vendor private (_SUN) or multi-vendor (_EXT or _ARB) 106 extensions. For this extension, we are defining a new 107 replacement code attribute that is part of the vertex state 108 and is expected to be processed directly by hardware. Given 109 this, we have defined the replacement codes as small integer 110 values (1, 2, and 3) that correspond with what the hardware 111 wants to see. The cost for having these values be different, 112 especially for replacement codes in a vertex array, are too 113 great. 114 115 Another reason for not using constants in the range of 116 extension enums is that if this ever became part of the core 117 after first being an extension, or even if it became a 118 multi-vendor extension after first being a Sun-private 119 extension, then the codes would change. This would be 120 unworkable for an attribute such as this, since it is part of 121 the vertex pipeline. 122 123 We need to ensure that our current plan of defining 124 replacement codes outside the range of extension enums is not 125 violating any rules. I think that this shouldn't be a problem 126 since the replacement codes themselves are really just 127 parameters to the replacement code command. As such, they are 128 just bit patterns and shouldn't need to be unique. 129 130 131New Procedures and Functions 132 133 void ReplacementCodeuiSUN(uint code); 134 135 void ReplacementCodeusSUN(ushort code); 136 137 void ReplacementCodeubSUN(ubyte code); 138 139 void ReplacementCodeuivSUN(const uint *code); 140 141 void ReplacementCodeusvSUN(const ushort *code); 142 143 void ReplacementCodeubvSUN(const ubyte *code); 144 145 void ReplacementCodePointerSUN(enum type, 146 sizei stride, 147 const void *pointer); 148 149 150New Tokens 151 152 Accepted by the <mode> parameter of Begin, DrawArrays, 153 DrawElements, MultiDrawArraysSUN, MultiDrawArraysEXT, 154 MultiDrawElementsSUN, and MultiDrawElementsEXT: 155 156 TRIANGLE_LIST_SUN 0x81D7 157 158 Accepted by the by the <pname> parameter of GetBooleanv, 159 GetIntegerv, GetFloatv, and GetDoublev: 160 161 REPLACEMENT_CODE_SUN 0x81D8 162 163 Accepted by the <code> parameter of ReplacementCode{ui,us,ub}[v]SUN: 164 165 RESTART_SUN 0x01 166 REPLACE_MIDDLE_SUN 0x02 167 REPLACE_OLDEST_SUN 0x03 168 169 Accepted by the <array> parameter of EnableClientState and 170 DisableClientState, and by the <cap> parameter of IsEnabled: 171 172 REPLACEMENT_CODE_ARRAY_SUN 0x85C0 173 174 Accepted by the <pname> parameter of GetBooleanv, GetIntegerv, 175 GetFloatv, and GetDoublev: 176 177 REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1 178 REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2 179 180 Accepted by the <pname> parameter of GetPointerv: 181 182 REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3 183 184 185 Accepted by the <format> parameter of InterleavedArrays: 186 187 R1UI_V3F_SUN 0x85C4 188 R1UI_C4UB_V3F_SUN 0x85C5 189 R1UI_C3F_V3F_SUN 0x85C6 190 R1UI_N3F_V3F_SUN 0x85C7 191 R1UI_C4F_N3F_V3F_SUN 0x85C8 192 R1UI_T2F_V3F_SUN 0x85C9 193 R1UI_T2F_N3F_V3F_SUN 0x85CA 194 R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB 195 196 197Additions to Chapter 2 of the GL Specification (OpenGL Operation) 198 199 Replacement Code 200 ---------------- 201 The replacement code is a per-vertex state attribute that controls 202 triangle vertex replacement for the triangle list primitive; it is 203 ignored for all other primitives. This state attribute is set by 204 the ReplacementCodeSUN command. Since it is part of the vertex state, 205 the ReplacementCodeSUN command may appear within a Begin/End pair. The 206 replacement code is an enum with 3 values, RESTART_SUN, 207 REPLACE_MIDDLE_SUN, and REPLACE_OLDEST_SUN. 208 209 Note that the replacement code follows the same rules as other 210 per-vertex state attributes. The current value of the replacement 211 code state attribute affects subsequent vertices until the next 212 time the ReplacementCodeSUN command is executed, updating the value 213 of the state attribute. This means that a replacement code that is 214 set outside of a Begin/End will affect subsequent triangle lists in 215 which the replacement code is not set. Similarly, the value of the 216 last replacement code set within a Begin/End will affect subsequent 217 triangle lists in which the replacement code is not set. 218 219 Triangle List 220 ------------- 221 A triangle list primitive is a series of triangles that are 222 connected according to the replacement codes associated with each 223 vertex in the list. A triangle list is specified by giving a 224 series of defining vertices between a Begin/End pair when Begin is 225 called with TRIANGLE_LIST. As with a triangle strip and a triangle 226 fan, the first three vertices define a triangle. The order of the 227 three vertices is significant. Subsequent vertices either define a 228 triangle that is connected to the previous triangle using the new 229 vertex and two vertices from the previous triangle, or they restart 230 a new triangle, depending on the value specified by the replacement 231 code state. The edge flag attribute is ignored by the triangle list 232 primitive. If PolygonMode is set to LINE or POINT, then all edges 233 or vertices are drawn (as with TRIANGLE_STRIP and TRIANGLE_FAN). 234 235 In addition to the current vertex, the state required to support 236 triangle lists consists of a 2-bit vertex counter that indicates 237 the number of vertices since the beginning of the list or since a 238 restart, two stored processed vertices, and a one-bit pointer 239 indicating the order of drawing (oldest-middle-current versus 240 middle-oldest-current). 241 242 The rules for determining when to draw a triangle and what vertices 243 to use and in what order are as follows: 244 245 1. When a BEGIN command is called with TRIANGLE_LIST, the vertex 246 counter is set to 0. 247 248 2. When a new vertex is completed, the following logic is used to 249 process the vertex: 250 251 if (vertex_counter == 0) { 252 vertex_counter = 1 253 drawing_order = 0 254 vertexA = currentVertex 255 } 256 else if (vertex_counter == 1) { 257 vertex_counter = 2 258 vertexB = currentVertex 259 } 260 else if (vertex_counter == 2) { 261 vertex_counter = 3 262 draw(vertexA, vertexB, currentVertex) 263 } 264 else { 265 if (repl_code == RESTART) { 266 vertex_counter = 1 267 drawing_order = 0 268 vertexA = currentVertex 269 } 270 else { 271 if (repl_code == REPLACE_OLDEST) 272 drawing_order = !drawing_order 273 274 if (drawing_order == 0) 275 draw(vertexA, vertexB, currentVertex) 276 else 277 draw(vertexB, vertexA, currentVertex) 278 279 if (repl_code == REPLACE_OLDEST) 280 vertexA = vertexB 281 vertexB = currentVertex 282 } 283 } 284 285 If a triangle list has fewer than 3 vertices then no triangles are 286 drawn. If a triangle list has fewer than 2 vertices following a 287 vertex with a RESTART replacement code, then the restart is 288 ignored, along with the one vertex after the restart, if present. 289 290 Because the replacement code is ignored for the first vertex and 291 the two vertices immediately following a restart, a constant 292 replacement code has a well-defined, consistent semantic. If the 293 replacement code for each vertex is REPLACE_OLDEST, then a triangle 294 strip will be drawn. If the replacement code for each vertex is 295 REPLACE_MIDDLE, then a triangle fan will be drawn. If the 296 replacement code for each vertex is RESTART, then isolated 297 triangles will be drawn. 298 299 The following example illustrates the use of vertex replacement 300 within a single triangle list to draw triangle strips, triangle 301 fans, isolated triangles, and, finally, a triangle strip that 302 switches to a fan and back to a strip without a restart. In this 303 example REPLACE_OLDEST is abbreviated RO and REPLACE_MIDDLE is 304 abbreviated RM. Note that the initial RESTART replacement appears 305 in square brackets, indicating that it is an implicit restart; the 306 replacement code is ignored for the first vertex following a begin 307 command. The replacement code is also ignored for the two 308 vertices immediately following a restart. 309 310 2 4 6 311 V1 [RESTART] .-------.-------. 312 V2 -- /\ /\ / 313 V3 -- / \ / \ / 314 V4 RO / \ / \ / Triangle Strip 315 V5 RO / \/ \/ 316 V6 RO .-------.-------. 317 1 3 5 318 319 9.-------.10 320 /\ /\ 321 V7 RESTART / \ / \ 322 V8 -- / \ / \ 323 V9 -- / \/ \ 324 V10 RM 8.------.7-------.11 Triangle Fan 325 V11 RM 14\ /\ / 326 V12 RM \ / \ / 327 V13 RM \ / \ / 328 V14 RM \/ \/ 329 .-------. 330 13 12 331 332 16 19 333 V15 RESTART . . 334 V16 -- /\ /\ 335 V17 -- / \ / \ 336 V18 RESTART / \ / \ Isolated Triangles 337 V19 -- / \ / \ 338 V20 -- .--------. .--------. 339 15 17 18 20 340 341 22 24 26 342 .-----.-----. 343 V21 RESTART |\ |\ |\ 344 V22 -- | \ | \ | \ 345 V23 -- | \ | \ | .27 346 V24 RO | \ | \ | /\ 347 V25 RO | \| 25/ \ 348 V26 RO .-----.-----.---.28 Mixed Strip & Fan 349 V27 RO 21 23 /|\ | 350 V28 RM / | \ | 351 V29 RM / | \| 352 V30 RM .---.---.29 353 V31 RM 31\ /30 354 V32 RO \ / 355 . 356 32 357 358 359 360 Triangle list primitives may be drawn using vertex arrays in the 361 same manner as other primitives. The replacement code state flag 362 may be enabled as part of a vertex array operation. The 363 REPLACEMENT_CODE_ARRAY_SUN enum is used to enable or disable the 364 replacement code array using the EnableClientState and 365 DisableClientState functions. 366 367 The following function defines the type, stride, and pointer for 368 the replacement code data. 369 370 void ReplacementCodePointerSUN(enum type, 371 sizei stride, 372 const void *pointer); 373 374 Legal values for type are UNSIGNED_BYTE, UNSIGNED_SHORT, and 375 UNSIGNED_INT. As with other vertex state, the value of the 376 replacement code attribute is undefined after a vertex array 377 command has been executed. 378 379 The following describes the memory layout of the new interleaved 380 array types. These new types may be used as the format parameter 381 of the InterleavedArrays function. 382 383 format pt pc pn pv s 384 --------------------- ------ ------ ------ ------ ------ 385 R1UI_V3F i i+3f 386 R1UI_C4UB_V3F i i+c i+c+3f 387 R1UI_C3F_V3F i i+3f i+6f 388 R1UI_N3F_V3F i i+3f i+6f 389 R1UI_C4F_N3F_V3F i i+4f i+7f i+10f 390 R1UI_T2F_V3F i i+2f i+5f 391 R1UI_T2F_N3F_V3F i i+2f i+5f i+8f 392 R1UI_T2F_C4F_N3F_V3F i i+2f i+6f i+9f i+12f 393 394Where i is sizeof(UNSIGNED_INT) rounded up to the nearest multiple of 395f. The replacement code pointer always starts at offset 0 from the 396interleaved array pointer. 397 398 399Additions to Chapter 3 of the GL Specification (Rasterization) 400 401 None 402 403 404Additions to Chapter 4 of the GL Specification (Per-Fragment Operations 405and the Framebuffer) 406 407 None 408 409 410Additions to Chapter 5 of the GL Specification (Special Functions) 411 412 None 413 414 415Additions to Chapter 6 of the GL Specification (State and State Requests) 416 417 None 418 419Additions to the GLX / WGL / AGL Specifications 420 421 None 422 423GLX Protocol 424 425 Three rendering commands are sent to the server as part of 426 the glXRender request: 427 428 ReplacementCodeuiSUN 429 2 8 rendering command length 430 2 16388 rendering command opcode 431 4 CARD32 code 432 433 ReplacementCodeubSUN 434 2 8 rendering command length 435 2 16389 rendering command opcode 436 1 CARD8 code 437 1 CARD8 pad 438 2 CARD16 pad 439 440 ReplacementCodeusSUN 441 2 8 rendering command length 442 2 16390 rendering command opcode 443 2 CARD16 code 444 2 CARD16 pad 445 446 447Errors 448 449 INVALID_ENUM is generated if ReplacementCodePointerSUN parameter 450 <type> is not UNSIGNED_BYTE, UNSIGNED_SHORT, or UNSIGNED_INT. 451 452 INVALID_VALUE is generated if ReplacementCodePointerSUN parameter 453 <stride> is negative. 454 455 456New State 457 458 Get Value Get Command Type Initial Value 459 --------- ----------- ---- ------------- 460 REPLACEMENT_CODE_SUN GetIntegerv Z4 REPLACE_OLDEST 461 REPLACEMENT_CODE_ARRAY_SUN IsEnabled B False 462 REPLACEMENT_CODE_ARRAY_TYPE_SUN GetIntegerv Z3 UNSIGNED_INT 463 REPLACEMENT_CODE_ARRAY_STRIDE_SUN GetIntegerv Z+ 0 464 REPLACEMENT_CODE_ARRAY_POINTER_SUN GetPointerv Y 0 465 466 Get Value Attribute 467 --------- --------- 468 REPLACEMENT_CODE_SUN current 469 REPLACEMENT_CODE_ARRAY_SUN vertex-array 470 REPLACEMENT_CODE_ARRAY_TYPE_SUN vertex-array 471 REPLACEMENT_CODE_ARRAY_STRIDE_SUN vertex-array 472 REPLACEMENT_CODE_ARRAY_POINTER_SUN vertex-array 473 474New Implementation Dependent State 475 476 None 477 478Revision History 479 480 6/25/99 Added fields from the new extension template. 481