1Name 2 3 SGIX_hyperpipe 4 5Name Strings 6 7 GLX_SGIX_hyperpipe 8 9Contact 10 11 Jon Leech, SGI (ljp 'at' sgi.com) 12 13Status 14 15 Shipping on SGI Infinite Reality and Ultimate Vision systems. 16 17Version 18 19 Last Modified Date: 2004/07/21 20 Revision: $Header: //depot/main/doc/registry/extensions/SGI/hyperpipe_group.spec#14 $ 21 22Number 23 24 307 25 26Dependencies 27 28 GLX 1.2 is required 29 SGIX_swap_control affects the definition of this extension. 30 31Overview 32 33 Even though graphics hardware is constantly improving in speed, there 34 will always be applications that require more performance than is 35 available from a single pipeline. In order to overcome these limits, 36 it is possible to parallelize the rendering task across multiple 37 pipes; the image outputs of these pipes must then be assembled into 38 a single display output. This group of pipes is termed a hyperpipe; 39 the pipes involved must be physically cabled together in some way 40 to form a hyperpipe network. Typically a hyperpipe network uses one 41 of the pipes to assemble the rendered images and drive the display. 42 43 In a hyperpipe network, the rendering task may be divided by rendering 44 each successive frame on a different hardware pipe (temporal division); 45 by dividing the frame into rectangular subregions and rendering each 46 on a different pipe (spatial division); or by a combination of these 47 two techniques. Specific hardware implementations may impose limits 48 on how rendering may be subdivided; but in general it is possible to 49 use a subset of the pipes connected to a hyperpipe network if desired. 50 51 This extension provides a means for configuring and managing a group 52 of rendering pipes which work together to produce a single display. 53 Typically, a hyperpipe application will be multithreaded, with 54 one thread per pipe; each thread needs to create its own rendering 55 context. The hyperpipe extension allows these rendering threads to 56 communicate with the hardware. 57 58 The API calls allow an application to : 59 60 o Determine the physical configuration of a hyperpipe network. 61 62 o Configure the hyperpipe. The hyperpipe configuration used by the 63 application may be a subset of the physical hyperpipe network. 64 The rendering task may be divided in time slices (temporally divided), 65 in rectangular regions of a single frame (spatially divided), or both. 66 The hyperpipe configuration is subject to hardware constraints. 67 68 For example, on a hyperpipe network consisting of five pipes, it 69 would be possible to configure a rendering task in two time slices, 70 with each slice being rendered by two pipes; thus using four total 71 pipes. (The fifth pipe would not be used in the hyperpipe, and 72 could be used for normal non-hyperpipe rendering and display). 73 74 o Maintain state to manage the glXSwapBuffers() call correctly. In 75 spatial subdivision, swap cannot occur until all pipes rendering 76 the next frame have completed; and in temporal subdivision, swap 77 cannot occur until the appropriate time. Swap management is 78 handled by the displaying pipe. 79 80 o Redirect resize parameters correctly; typically resize is handled 81 by the displaying pipe, and must be managed synchronously with 82 swap. 83 84 o Balance load among the pipes in the spatial subdivision case. 85 86 o Clean up operations when a hyperpipe application terminates 87 (either normally or due to error). 88 89 This extension adds to the set of conditions that must be met before 90 a buffer swap can take place. 91 92Issues and Notes 93 94 o This extension will work only on graphics pipelines with suitable 95 hyperpipe hardware installed. 96 97 98New Procedures and Functions 99 100 The following structure definitions are used by the extension: 101 102 /* 103 * pipeName uniquely names a pipe in the form ":display.screen" 104 * networkId is a unique physical hyperpipe network ID. 105 */ 106 typedef struct { 107 char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; 108 int networkId; 109 } GLXHyperpipeNetworkSGIX; 110 111 /* 112 * pipeName uniquely names a pipe in the form ":display.screen" 113 * channel is the channel number associated with the display pipe. 114 * participationType is a bitmask describing the attributes of a 115 * participating pipe. It may contain one or more of the 116 * attribute bits 117 * GLX_HYPERPIPE_DISPLAY_PIPE_SGIX 118 * GLX_HYPERPIPE_RENDERING_PIPE_SGIX 119 * timeSlice is ignored for GLX_HYPERPIPE_DISPLAY_PIPE_SGIX only. 120 */ 121 typedef struct { 122 char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; 123 int channel; 124 unsigned int participationType; 125 int timeSlice; 126 } GLXHyperpipeConfigSGIX; 127 128 /* 129 * pipeName uniquely names a pipe in the form ":display.screen" 130 * src origin/size are in managed area coordinates (pixels). 131 * dest origin/size are in output channel display coordinates. 132 */ 133 typedef struct { 134 char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; 135 int srcXOrigin; 136 int srcYOrigin; 137 int srcWidth; 138 int srcHeight; 139 int destXOrigin; 140 int destYOrigin; 141 int destWidth; 142 int destHeight; 143 } GLXPipeRect; 144 145 /* 146 * pipeName uniquely names a pipe in the form ":display.screen" 147 * origin/size are in managed area coordinates (pixels) 148 */ 149 typedef struct { 150 char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; 151 int XOrigin; /* pixels in managed area */ 152 int YOrigin; 153 int maxHeight; 154 int maxWidth; 155 } GLXPipeRectLimits; 156 157 GLXHyperpipeNetworkSGIX * 158 glXQueryHyperpipeNetworkSGIX( 159 Display *dpy, int *npipes); 160 161 int glXHyperpipeConfigSGIX( 162 Display *dpy, int networkId, int npipes, 163 GLXHyperpipeConfigSGIX *cfg, int *hpId); 164 165 GLXHyperpipeConfigSGIX * 166 glXQueryHyperpipeConfigSGIX( 167 Display *dpy, int hpId, int *npipes); 168 169 int glXDestroyHyperpipeConfigSGIX( 170 Display * dpy, int hpId); 171 172 int glXBindHyperpipeSGIX( 173 Display *dpy, int hpId); 174 175 int glXQueryHyperpipeBestAttribSGIX( 176 Display *dpy, int timeSlice, int attrib, int size, 177 void *attribList, void *returnAttribList); 178 179 int glXHyperpipeAttribSGIX( 180 Display *dpy, int timeSlice, int attrib, int size, 181 void *attribList); 182 183 int glXQueryHyperpipeAttribSGIX( 184 Display *dpy, int timeSlice, int attrib, int size, 185 void *returnAttribList); 186 187 188 189New Tokens 190 191 Accepted by the <attribute> parameter of glXQueryContextInfoEXT: 192 193 GLX_HYPERPIPE_ID_SGIX 0x8030 194 195 Maximum length of the string naming a hyperpipe: 196 197 GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX 80 198 199 Bits that may be set in the <participationType> bitfield of the 200 GLXHyperpipeConfigSGIX argument passed into glXHyperpipeConfigSGIX 201 and returned by glXQueryHyperpipeConfigSGIX: 202 203 GLX_HYPERPIPE_DISPLAY_PIPE_SGIX 0x00000001 204 GLX_HYPERPIPE_RENDER_PIPE_SGIX 0x00000002 205 206 Accepted by the <attrib> parameter of glXQueryHyperpipeAttribSGIX: 207 208 GLX_PIPE_RECT_SGIX 0x00000001 209 GLX_PIPE_RECT_LIMITS_SGIX 0x00000002 210 GLX_HYPERPIPE_STEREO_SGIX 0x00000003 211 GLX_HYPERPIPE_PIXEL_AVERAGE_SGIX 0x00000004 212 213 Accepted by the <attrib> parameters of and glXHyperpipeAttribSGIX: 214 215 GLX_PIPE_RECT_SGIX 216 GLX_HYPERPIPE_STEREO_SGIX 217 GLX_HYPERPIPE_PIXEL_AVERAGE_SGIX 218 219 Accepted by the <attrib> parameter of 220 glXQueryHyperpipeBestAttribSGIX: 221 222 GLX_PIPE_RECT_SGIX 223 GLX_PIPE_RECT_LIMITS_SGIX 224 225 New error codes: 226 227 GLX_BAD_HYPERPIPE_CONFIG_SGIX 91 228 GLX_BAD_HYPERPIPE_SGIX 92 229 230 231Additions to the GLX 1.3 Specification 232 233 Add new section 3.X "Hyperpipes" 234 235 Hyperpipes are collections of graphics pipes that may operate 236 together to generate images. The pipes may be split either spatially 237 (with different pipes rendering different subrectangles of an output 238 image), temporally (with different pipes rendering different time 239 slices of an output image), or both. 240 241 Section 3.X.1 "Hyperpipe Networks" 242 243 To determine the physical connectivity of hyperpipes in a system, 244 call 245 246 GLXHyperpipeNetworkSGIX *glXQueryHyperpipeNetworkSGIX( 247 Display *dpy, int *npipes) 248 249 There may be more than one hyperpipe network in the system. The 250 networks are numbered sequentially. 251 252 glXQueryHyperpipeNetworkSGIX returns a pointer to an array of 253 GLXHyperpipeNetworkSGIX structures describing the availalable pipes. 254 This list is sorted on the physical hyperpipe network number (the 255 <networkId> field of the GLXHyperpipeNetworkSGIX structure). 256 Networks are numbered sequentially from 0. 257 258 The number of pipes is returned in <*npipes>. If no hyperpipe 259 network is defined in the system, NULL is returned. returns NULL. 260 Use XFree to free the array returned by 261 glXQueryHyperpipeNetworkSGIX. 262 263 264 Section 3.X.2 "Hyperpipe Configuration" 265 266 To specify the logical configuration of a hyperpipe, call 267 268 int glXHyperpipeConfigSGIX(Display *dpy, int networkId, 269 int npipes, GLXHyperpipeConfigSGIX *cfg, int *hpId); 270 271 The physical connectivity of a hyperpipe is determined by the 272 cabling of the hardware. It is possible to use only a subset of the 273 pipes physically connected together. These participant pipes may 274 contribute to the hyperpipe in a temporally interleaved manner 275 and/or spatially subdivided manner. The configuration information 276 specifies which pipes participate in the hyperpipe. It also 277 specifies the relative order of these pipes and their type of 278 contribution (spatial or temporal). This configuration cannot be 279 arbitrary and is subject to some hardware constraints. 280 281 <networkId> specifies the physical hyperpipe network ID to be 282 configured. <npipes> specifies the total number of pipes in the 283 configuration. <cfg> is a pointer to an array of <npipes> 284 GLXHyperpipeConfigSGIX structures, each specifying the configuration 285 for a single pipe. 286 287 The <pipeName> field of each <cfg> structure specifies the pipe ID 288 of that pipe, and the <channel> field specifies a channel number 289 associated with that pipe. 290 291 If the <participationType> field contains 292 GLX_HYPERPIPE_RENDER_PIPE_SGIX, the pipe is designated to render 293 data for a subset of the pipeline (spatially or temporally). If the 294 field contains GLX_HYPERPIPE_DISPLAY_PIPE_SGIX, the pipe is 295 designated to assemble rendered data and display it on that pipe's 296 local channel. There can be multiple rendering pipes, but only one 297 display pipe in a network. 298 299 The <timeSlice> field specifies the time slice to which a rendering 300 pipe contributes, and must be in the range 0 to <npipes>-1. 301 302 On success, a unique hyperpipe ID is generated and returned in the 303 integer pointed to by <hpId>. Subsequent calls may require a valid 304 hyperpipe ID parameter. In the case of a multi-process application, 305 the master process should configure the hyperpipe, and child 306 processes should then use the same hyperpipe ID as the master 307 process. The hyperpipe ID is global across multiple processes. If 308 another process attempts a configuration using already allocated 309 pipes, the second configuration will fail. 310 311 If the pipes contribute in a spatially subdivided manner, then the 312 screen is divided evenly between them. This division can be 313 subsequently changed via calls to glXHyperpipeAttribSGIX(). 314 315 glXHyperpipeConfigSGIX() returns GLX_BAD_HYPERPIPE_CONFIG_SGIX if 316 the specified <cfg> is invalid. 317 318 319 To query the details of a hyperpipe configuration, call 320 321 GLXHyperpipeConfigSGIX *glXQueryHyperpipeConfigSGIX( 322 Display *dpy, int hpId, int *npipes); 323 324 <hpId> is the ID of the hyperpipe configuration to query. It must 325 have been obtained from a previous call to glXHyperpipeConfigSGIX. 326 327 glXQueryHyperpipeConfigSGIX returns a pointer to an array of 328 GLXHyperpipeConfigSGIX structures describing the pipes in the 329 configuration. The parameters of the structures are as described for 330 glXHyperpipeConfigSGIX. 331 332 The number of pipes is returned in <*npipes>. If <hpId> is not a 333 valid hyperpipe ID, NULL is returned. Use XFree to free the array 334 returned by glXQueryHyperpipeConfigSGIX. 335 336 337 To destroy a hyperpipe configuration, call 338 339 int glXDestroyHyperpipeConfigSGIX(Display * dpy, int hpId); 340 341 <hpId> is the ID of the hyperpipe configuration to destroy. It must 342 have been obtained from a previous call to glXHyperpipeConfigSGIX. 343 All process should unbind from <hpId> by calling 344 glXBindHyperipipeSGIX(dpy, -1) before destroying the hyperpipe 345 configuration. 346 347 On success, the resources associated with <hpId> are destroyed and 348 <hpId> is no longer a valid hyperpipe ID. 349 350 glXHyperpipeConfigSGIX() returns GLX_BAD_HYPERPIPE_SGIX if there is 351 no valid hyperpipe configuration with the specified ID. 352 353 354 Section 3.X.2 "Binding Hyperpipes" 355 356 To bind the current rendering context to a hyperpipe, call 357 358 int glXBindHyperpipeSGIX(Display *dpy, int hpId); 359 360 This establishes an association between the calling process, the 361 current context, and the hyperpipe configuration with ID <hpId>. 362 When this rendering context is destroyed, the hyperpipe operations 363 associated with this hyperpipe group may be terminated. 364 365 Every process participating in a hyperpipe should call 366 glXBindHyperpipeSGIX after creating and choosing a rendering 367 context. Hyperpipe requests to this process will not begin until 368 this call is made. 369 370 It is possible to determine if a hyperpipe is bound by calling 371 glXQueryContextInfoEXT with the attribute GLX_HYPERPIPE_ID_SGIX. 372 373 Calling glXBindHyperpipeSGIX with <hpId> == -1 unbinds the current 374 rendering context from the hyperpipe. If no hyperpipe is bound, this 375 call is ignored and no error is generated. 376 377 A process can bind to only one hyperpipe at any time. In order to 378 bind to another hyperpipe, the process must explicitly unbind from 379 the current hyperpipe. If a process calls glXBindHyperpipeSGIX() 380 more than once without an intervening unbind, then the subsequent 381 bind will fail. 382 383 glXBindHyperpipeSGIX returns GLX_BAD_HYPERPIPE_SGIX if <hpId> is not 384 a valid hyperpipe ID. 385 386 387 To determine the best possible hyperpipe attributes subject to 388 constraints imposed by the hyperpipe implementation, call 389 390 int glXQueryHyperpipeBestAttribSGIX(Display *dpy, 391 int timeSlice, int attrib, int size, void *attribList, 392 void *returnAttribList); 393 394 <timeSlice> specifies the time slice for which <attrib> is queried. 395 Its value may range from 0 to the maximum number of time slices for 396 which the hyperpipe is configure. 397 398 <attrib> is a bitmask specifying the type of the attribute for which 399 the best attributes are to be determined. 400 401 <size> specifies the total size, in bytes, of the arrays pointed to 402 by <attribList> and <returnAttribList>. 403 404 <attribList> is a pointer to an array of requested values. The array 405 contains one value, of type determined by <attrib>, for each pipe 406 contributing to the specified time slice. 407 408 <returnAttribList> is a pointer to an array in which returned values 409 are copied. The array must be large enough to contain one value, of 410 type determined by <attrib>, for each pipe contributing to the 411 specified time slice (in other words, must be the same size as the 412 array pointed to by <attribList>). Values returned will be as close 413 as possible to those specified in <attribList>, subject to the 414 implementation constraints. 415 416 If <attrib> is GLX_PIPE_RECT, the subrectangles composing a 417 hyperpipe rectangle during <timeSlice> are queried. <attribList> 418 must point to an array of <n> GLXPipeRect structures, one for each 419 pipe contributing to the specified <timeSlice> of the currently 420 bound hyperpipe, each defining an input source rectangle (origin, 421 width, and height in the managed area), and an output destination 422 rectangle (origin, width, and height in the output display area). In 423 this case <size> must be <n> * sizeof(GLXPipeRect). 424 425 If <attrib> is GLX_PIPE_RECT_LIMITS, the maximum size of the 426 subrectangles during <timeSlice> are queried. <attribList> must 427 point to an array of <n> GLXPipeRectLimits structures, each defining 428 an origin and maximum width and height in the managed area. In this 429 case <size> must be <n> * sizeof(GLXPipeRectLimits), where <n> is 430 the number of pipes participating in <timeSlice>. 431 432 glXQueryHyperpipeBestAttribSGIX returns GLX_BAD_HYPERPIPE_SGIX if 433 there is no valid hyperpipe configuration bound to the current 434 context, or if <size> is too small for the amount of data 435 implied by <timeSlice> and <attrib>. 436 437 glXQueryHypepipeBestAttribSGIX returns GLX_BAD_VALUE if <attrib> is 438 not one of GLX_PIPE_RECT or GLX_PIPE_RECT_LIMITS, or if any of the 439 elements in <attribList> cannot be altered to satisfy the 440 constraints of the current hyperpipe. 441 442 443 444 Section 3.X.3 "Hyperpipe Attributes" 445 446 To set hyperpipe attribute values, call 447 448 int glXHyperpipeAttribSGIX(Display *dpy, int timeSlice, 449 int attrib, int size, void *attribList); 450 451 <timeSlice>, <attrib>, and <size> have the same meaning as the 452 corresponding attributes of glXQueryHyperpipeBestAttribSGIX. 453 454 If <attrib> is GLX_PIPE_RECT_SGIX, <attribList> must point to an 455 array of <n> subrectangles defined by GLXPipeRect structures, one for 456 each pipe contributing to the specified <timeSlice> of the currently 457 bound hyperpipe. This allows load balancing the pipes. In this case 458 <size> must be <n> * sizeof(GLXPipeRect). 459 460 If <attrib> is GLX_HYPERPIPE_STEREO_SGIX, <attribList> must point to 461 an integer controlling alternation between pipes in the hyerpipe. 462 One pipe provides the left eye data, and the second provides the 463 right eye data. An attribute value of 1 enables stereo for the 464 corresponding pipe, and an attribute value of 0 disables stereo. In 465 this case <size> = sizeof(int). 466 467 If <attrib> is GLX_HYPERPIPE_PIXEL_AVERAGE_SGIX, <attribList> must 468 point to an integer controlling averaging of pixel data. An 469 attribute value of 1 enables an averaging mode in which 470 corresponding pixel values from all pipes in the hyperpipe are 471 averaged together before being sent to the display, and an attribute 472 value of 0 disables averaging. In this case <size> = sizeof(int). 473 474 glXHyperpipeAttribSGIX is swap synchronous; that is, the attributes 475 are not changed until glXSwapBuffers is called for the corresponding 476 window. 477 478 glXHyperpipeAttribSGIX returns GLX_BAD_HYPERPIPE_SGIX if there is no 479 valid hyperpipe configuration bound to the current context, or if 480 <size> is too small for the amount of data implied by <timeSlice> 481 and <attrib>. 482 483 glXHypepipeAttribSGIX returns GLX_BAD_VALUE if <attrib> is not one 484 of GLX_PIPE_RECT_SGIX, GLX_HYPERPIPE_STEREO_SGIX, or 485 GLX_HYPERPIPE_PIXEL_AVERAGE_SGIX. 486 487 488 To query hyperpipe attribute values, call 489 490 int glXQueryHyperpipeAttribSGIX(Display *dpy, int timeSlice, 491 int attrib, int size, void *returnAttribList); 492 493 <timeSlice>, <attrib>, and <size> have the same meaning as the 494 corresponding attributes of glXHyperpipeAttribSGIX. 495 496 If <attrib> is GLX_PIPE_RECT_SGIX, <attribList> must point to an 497 array of <n> GLXPipeRect structures, one for each pipe contributing 498 to the specified <timeSlice> of the currently bound hyperpipe. The 499 subrectangles corresponding to each pipe are returned in 500 <attribList>. In this case <size> must be <n> * sizeof(GLXPipeRect). 501 502 If <attrib> is GLX_PIPE_RECT_LIMITS_SGIX, <attribList> must point to 503 an array of <n> GLXPipeRectLimits structures, one for each pipe 504 contributing to the specified <timeSlice> of the currently bound 505 hyperpipe. The maximum width and height of the subrectangles 506 corresponding to each pipe are returned in <attribList>. In this 507 case <size> must be <n> * sizeof(GLXPipeRectLimits). 508 509 If <attrib> is GLX_HYPERPIPE_STEREO_SGIX, <attribList> must point to 510 an integer. A return value of 1 indicates that stereo is enabled 511 while a return value of 0 indicates that stereo is disabled. In this 512 case <size> = sizeof(int). 513 514 If <attrib> is GLX_HYPERPIPE_PIXEL_AVERAGE_SGIX, <attribList> must 515 point to an integer. A return value of 1 indicates that pixel 516 averaging is enabled, while a return value of 0 indicates that pixel 517 averaging is disabled. In this case <size> = sizeof(int). 518 519 glXQueryHyperpipeAttribSGIX returns GLX_BAD_HYPERPIPE_SGIX if there 520 is no valid hyperpipe configuration bound to the current context, or 521 if <size> is too small for the amount of data implied by <timeSlice> 522 and <attrib>. 523 524 glXQueryHypepipeAttribSGIX returns GLX_BAD_VALUE if <attrib> is not 525 one of GLX_PIPE_RECT_SGIX, GLX_PIPE_RECT_LIMITS_SGIX, 526 GLX_HYPERPIPE_STEREO_SGIX, or GLX_HYPERPIPE_PIXEL_AVERAGE_SGIX. 527 528 529 530 Add to section 3.2.6, Double Buffering: 531 532 When a hyperpipe is bound to the current context, all pipes 533 participating in a single time slice will swap together. 534 glXSwapBuffers may be called even for a single-buffered visual when 535 a hyperpipe is bound, to cause the hyperpipe to switch to the next 536 time slice. 537 538 When a pipe in a hyperpipe configuration completes rendering of its 539 portion of the framebuffer, completion is indicated by via a call to 540 glXSwapBuffers. After all the pipes contributing to a particular 541 time slice indicate completion, the hyperpipe requests for this time 542 slice may begin. 543 544 545 [Add to table listing GLX context attributes for glXQueryContextInfoEXT] 546 547 GLX context attribute type context information 548 --------------------- ---- ------------------- 549 GLX_HYPERPIPE_ID_SGIX XID hyperpipe id, if the rendering context 550 is associated with a hyperpipe 551 552 553Errors 554 555 Errors specific to hyperpipes are defined in the specification 556 language. GLX_BAD_CONTEXT may be returned by any hyperpipe call if 557 there is no valid current context. 558 559 560Implementation Notes 561 562 glXQueryHyperpipeBestAttribSGIX and glXHyperpipeAttribSGIX are 563 currently supported only on InfinitePerformance systems. 564 565 On InfinitePerformance systems, GLX_PIPE_RECT_SGIX requires that X 566 origins and sizes be aligned on 4 pixel boundaries. 567 568 569 The hyperpipe context ensures that resize parameters may be 570 synchronized across a hyperpipe. The details of this synchronization 571 are system-dependent, and may for example use the /dev/gfx device on 572 SGI IRIX systems. 573 574 575 In SGI implementations using external compositors (e.g. SG2), the 576 distinction between display and render pipes in the 577 <participationType> bitfield is ignored. In principle both bits 578 could be set for a single pipe, but no implementations in which this 579 mode is supported, or makes sense, have yet been developed. 580 581 582 In SGI implementations, the pixel averaging mode controlled by 583 GLX_HYPERPIPE_PIXEL_AVERAGE_SGIX is meant to be used for full-screen 584 antialiasing, with each pipe in a time slice contributing jittered 585 samples for each pixel in the output image. 586 587 588 The SGI implementation uses an internal constant 589 GLX_HYPERPIPE_PIPE_NPIPES_SGIX = 32. This token is not exposed in 590 the external API, and has not been placed in the public glxext.h 591 header file. 592 593Revision History 594 595 Revision 14, 2004/07/22 - closed out some open issues based on the 596 SGI implementation details. 597 598 Revision 13, 2004/07/21 - completely rewrote specification based on 599 the IRIX man pages. This should be substantially more complete than 600 the previous (1999) revision, and better correspond to what's 601 actually being shipped. 602