For a list of related topics, see Programming Interface for Generating Output Commands.
The functions described in this section generate output commands. You can direct these output commands to a renderer for immediate processing or you can store them in a structure resource.
PEXlib does not directly expose the specific protocol requests PEXRCStoreElements and PEXRCRenderOutputCommands. Instead, the request type argument, req_type, determines which of these two requests to use and when to use them to send the output commands to the PEX implementation. This argument must have one of four values: PEXOCRender, PEXOCRenderSingle, PEXOCStore or PEXOCStoreSingle. PEXOCRender and PEXOCRenderSingle cause PEXlib to format the output command into a PEXRCRenderOutputCommands request. This request causes the implementation to immediately render the output commands using the specified renderer when the implementation receives the request. PEXOCStore and PEXOCStoreSingle cause PEXlib to format the output command into a PEXRCStoreElements request. This request causes the implementation to store the output commands into the specified structure when the implementation receives the request. If the request type argument is not one of the values defined above, then the result is implementation-dependent.
To improve performance, PEXlib tries to pack output commands into single PEXRCRenderOutputCommands or PEXRCStoreElements requests. This packing, or buffering, of output commands normally occurs when the request type is PEXOCRender or PEXOCStore. When the request type is PEXOCRenderSingle or PEXOCStoreSingle, PEXlib forces the output command to be formatted into a single request by itself. This is useful, for example, for debugging purposes.
Applications should either use PEXOCStoreSingle when the structure's editing mode is PEXStructureReplace, or delete elements and use PEXStructureInsert to insert the new elements. See Structures for more detail. The result of the PEXRCStoreElements request when the specified structure's editing mode is set to PEXStructureReplace is unpredictable when using the request type PEXOCStore. The PEXRCStoreElements request replaces a range of elements in the structure, depending on how many output commands are in the request.
The number of output commands in a given request depends on too many variables to predict. PEXlib will not pack a single request that is too large to send to the server. However, if a single OC is too large to send, PEXlib causes the PEX server to issue a BadLength error. Invoke the PEXGetSizeOCs and XMaxRequestSize functions beforehand to determine if an OC is too large to send. See Introduction to PEXlib for more detail.
There are also a number of OC manipulation functions defined in Output Command Encode and Decode and in Sending Encoded Output Commands.
For a PHIGS workstation resource to process output commands for rendering, you must store the output commands in structures. The PHIGS workstation subset does not, in itself, support immediate mode rendering. See PHIGS Workstation Overview for more information on PHIGS workstations.
For a list of related topics, see Programming Interface for Generating Output Commands.
PEXlib offers two major argument interfaces for the output command functions: the explicit interface and the output command context, or OC Context (OCC) interface.
The explicit interface is the interface defined for PEXlib 5.1 and is included in the PEXlib 5.2 specification for backwards compatibility, so PEXlib 5.1 programs compile with PEXlib 5.2 libraries. Although you may still use the explicit interface, you are encouraged to use the OCC interface to take advantage of the performance and functional improvements available in PEXlib 5.2. The explicit interface uses the same first three arguments:
The explicit interface requires that you specify all arguments on every output command function you invoke.
Topics within this section include:
For a list of all the related topics, see Programming Interface for Generating Output Commands.
The output command context interface (introduced with PEXlib 5.2) requires that the first argument always be the OC context, replacing the three arguments listed above. The OC context is an opaque structure that contains many of the arguments that are commonly found in the output command functions. Your application uses a set of special OCC manipulation functions to modify the fields in the opaque OC context. Then your application uses the OC Context in subsequent invocations of output command functions. The OCC interface uses far fewer arguments than the explicit interface, making coding easier and improving performance in some implementations. See Output Command Context (OC Context or OCC) for the complete description of the OCC.
Note: the attribute and primitive output commands introduced after 5.1 do not offer the explicit argument interface format. This is to encourage the use of the OCC argument interface in newer applications over the older explicit interface.
Related topics include:
The OCC style functions for primitives that have facet and/or vertex data parameters allow you to supply the graphical data (coordinates, vertex attributes, facet attributes, and floating-point data) in packed, stride, or unpacked form. The packed form is the only form supported in PEXlib 5.1 and requires you to format the data into packed data structures defined by PEXlib. The stride form is more flexible and allows you to supply data formatted in application-defined structured arrays without the need to copy the data into the PEXlib-defined structures before invoking the PEXlib function. (Note: A "structured array", in this context, refers to an array of C language structures (as in struct) which is a common idiom employed in C language data structures, for example:
struct MyStruct { float x,y; } myData[30];)
The unpacked form allows you to supply the data in separate lists for each data type.
Related topics include:
On many machine architectures, data alignment can be very important for performance and correct execution. For example, some machines require that pointers point to word boundaries when accessing word-length data items. Because the OCC interface allows you to control the offset applied to pointers for data accesses, you should be extra careful when specifying OCC pointers and offsets to ensure that you are following your machine's data alignment policies.
Topics within this section include:
For a list of all the related topics, see Programming Interface for Generating Output Commands.
The OC Context maintains the state of some common PEXlib arguments across PEXlib function calls. The OC context enables you to set the desired values of these arguments and then reuse them by specifying just the OC Context in several subsequent function calls. This eliminates the need to re-specify these same arguments in every function call, reducing redundancy and improving performance in some environments.
The OC Context itself is an opaque data structure with members that are referred to as values. Programs cannot alter the values of the OC Context directly. Instead, programs must use additional function calls to manipulate the values of the context. This ensures that the PEXlib implementation is informed whenever an OC Context value is changed.
Related topics include:
The primary data structure used with the OC Context is the PEXOCCValues data structure which you use to set the value fields via the bitmask/value mechanism. It is important to realize that you do not alter the OC Context itself. You instead specify your desired changes in the PEXOCCValues data structure and use OCC functions to alter the OC Context with this data structure as input. The default values assigned to the OC Context, when your application creates it, are also given below:
typedef struct { /* DEFAULT Values */ Display *display; /* undefined */ PEXRenderer renderer; /* undefined */ PEXStructure structure; /* undefined */ PEXOCRequestType req_type; /* PEXOCRender */ int shape_hint; /* PEXShapeUnknown */ int ignore_edges; /* False */ int contour_hint; /* PEXContourUnknown */ int contours_all_one; /* False */ unsigned int facet_attributes; /* PEXGANone */ unsigned int line_vertex_attributes; /* PEXGANone */ unsigned int marker_vertex_attributes; /* PEXGANone */ unsigned int surface_vertex_attributes; /* PEXGANone */ unsigned int edge_attributes; /* PEXGANone */ unsigned int facet_fp_data_count; /* 0 */ unsigned int line_vertex_fp_data_count; /* 0 */ unsigned int marker_vertex_fp_data_count; /* 0 */ unsigned int surface_vertex_fp_data_count; /* 0 */ int color_type; /* PEXColorTypeRGB */ char *encoding_state; /* NULL Pointer */ int data_model; /* PEXDataPacked */ union { PEXOCCStrideData stride; PEXOCCUnpackedData unpacked; } data_model_specs; } PEXOCCValues; typedef struct { /* all members 0 */ int facet_stride; int vertex_stride; int facet_color_offset; int facet_normal_offset; int facet_fp_data_offset; int vertex_coord_offset; int vertex_color_offset; int vertex_normal_offset; int vertex_edge_offset; int vertex_radius_offset; int vertex_axes_offset; int vertex_angle_offset; int line_vertex_fp_data_offset; int marker_vertex_fp_data_offset; int surface_vertex_fp_data_offset; } PEXOCCStrideData; typedef struct { /* all members 0 */ int facet_color_size; int facet_normal_size; int facet_fp_data_count; int vertex_coord_size; int vertex_color_size; int vertex_normal_size; int vertex_edge_size; int vertex_radius_size; int vertex_axes_size; int vertex_angle_size; int line_vertex_fp_data_count; int marker_vertex_fp_data_count; int surface_vertex_fp_data_count; } PEXOCCUnpackedData;
The semantics of each member in the PEXOCCValues structure is the same as it is in the explicit interface.
Specify all size and offset members in terms of bytes. The fp_data_count members represent the number of floating-point values.
The encoding_state member is reserved for use by future internationalized text functions to retain character encoding state for languages that require it.
The data_model member indicates the data model used to pass vertex and facet data to OCC primitive functions. You should set this member to PEXDataPacked, PEXDataStride, or PEXDataUnpacked.
The OCC itself is defined as:
typedef struct _PEXOCC #ifdef PEXLIB_ILLEGAL_ACCESS { XExtData *ext_data; /* hook for extension */ /* PEXlib private data */ } #endif *PEXOCC;
You cannot access any members with the OCC directly. You must simply pass the OCC to functions that modify or use the contents of the context structure.
Related topics include:
To invoke the OC functions that use the OC Context, your application must first create an OC Context with the PEXCreateOCC function. This function returns an OC Context initialized with default values for future reference. The application can change the default context values when it creates the OC Context and/or can change values later by invoking the PEXChangeOCC function. These two functions set the value fields via a bitmask/value mechanism and are suitable when you are setting several values at once. There are also OC Context convenience functions that, through a simpler interface, enable you to set only one value per function in the OCC.
Here is a coded example of how to use the OC Context. The last two statements illustrate the difference between an OCC function and a non-OCC function:
PEXOCCValues ocvalues; unsigned int mask; PEXOCC myocc; ocvalues.display = my_display; PEXSetOCCValueMask(&mask, PEXOCCMDisplay); ocvalues.renderer = my_renderer; PEXSetOCCValueMask(&mask, PEXOCCMRenderer); ocvalues.color_type = PEXColorTypeRGB; PEXSetOCCValueMask(&mask, PEXOCCMColorType); ocvalues.surface_vertex_attributes = PEXGAColor; PEXSetOCCValueMask(&mask, PEXOCCMSurfaceVertexAttributes); myocc = PEXCreateOCC(&mask, &ocvalues); PEXOCCTriangleStrip(myocc, NULL, count, vertices); /* This is the old, explicit interface */ PEXTriangleStrip(display, resource_id, req_type, PEXGANone, PEXGAColor, 0, 0, PEXRGBFloat, NULL, count, vertices);
Note that it was not necessary to set the facet attributes member of the OCC to PEXGANone because PEXGANone is the default value in a newly created OCC.
Invoke the PEXFreeOCC function to deallocate the memory associated with the OC Context.
Topics within this section include:
For a list of all the related topics, see Programming Interface for Generating Output Commands.
There are three ways to provide facet and vertex data to PEXlib:
Related topics include:
For a list of all the related topics, see Programming Interface for Generating Output Commands.
Unlike the stride and unpacked interfaces, you can use the packed data interface with either OCC primitive functions or with non-OCC primitive functions. The use of the packed data interface with non-OCC functions, as with PEXlib 5.1 functions, is as follows (this example has no facet data and supplies colors and normals in the vertex data):
PEXVertexRGBNormal my_vertices[20]; PEXArrayOfVertex verts; /* code to init my_vertices */ verts.rgb_normal = my_vertices; PEXTriangleStrip(display, rend, PEXOCRender, 0, PEXGAColor | PEXGANormal, PEXColorTypeRGB, NULL, 20, verts);
You can also use packed data format with OCC style functions, which you may find useful when converting older code to use the OCC style functions:
PEXVertexRGBNormal my_vertices[20]; /* code to init my_vertices */
PEXOCCTriangleStrip(context, NULL, 20, my_vertices);
This usage assumes that you have already initialized the OC Context fields with the correct values. In particular, you need to set the display, renderer (or structure), req_type, surface_vertex_attributes, color_type, and data_model (PEXDataPacked, of course) fields. Unless these fields change, you only need to set these once. You do not need to set any fields in the data_model_specs union.
Also, you do not need the PEXArrayOfVertex union to pass the vertex data in the function. The type of the facet and vertex data parameters is PEXPointer, which allows you to pass any type in this parameter. This is important for the stride interface. However, for both facet and vertex data, you are responsible for making sure that the data you are passing accurately reflects the attributes that the data you are passing accurately reflects the attributes that you set in the facet or vertex attribute fields.
PEXlib does not supply a set of structure type definitions for facet or vertex data that include floating point data because there is no way to determine how many floating point numbers you want to supply with a facet or vertex. Therefore, you may find it convenient to design your own data structure to pass the facet or vertex parameters or some OC functions when using the PEXDataPacked data model. You need to design the data structure with the following ordering rules in mind:
For facet data, the required order is:
PEXColor* one of the PEXlib color types, if provided PEXVector normal, if provided float[n] floating point data, if provided
For vertex data, the required order is:
PEXCoord (or PEXCoord2D) center PEXColor* one of the PEXlib color types, if provided PEXVector normal, if provided unsigned int edges, if provided float[n] floating point data, if provided
As an example, if you wish to supply vertex data for FillArea using 3D coordinates, RGB floating-point colors and three floating-point numbers (for texture data), you would create a structure like this:
typedef struct { PEXCoord center; PEXColorRGB rgb; float texture_data[3]; } MY_PEXRGBTextureVertexData;
Remember to set the correct surface vertex attributes in the OCC. In this case you would make sure that the PEXGA2D flag is off, the PEXGAColor is on and the PEXGAFloatData flag is on. You set the color_type field in the OCC to PEXColorTypeRGB and the number of floats in the OCC to three.
You may then pass the address of an array of these structures directly in the OCC form of a function:
MY_PEXRGBTextureVertexData my_vertices[20]; /* code to init my_vertices */
PEXOCCTriangleStrip(context, NULL, 20, my_vertices);
Related topics include:
For a list of all the related topics, see Programming Interface for Generating Output Commands.
The stride interface allows you to access the facet and vertex data directly from application data structures if the data is arranged in a "structured array" format, where the application stores facet or vertex data in an array of structures; each structure in the structured array corresponds to data for a single facet or vertex along with other application specific data. You specify the size, or "stride" of each array element and the offsets of each of the facet or vertex data items within the array element. Using this format, you eliminate the need to copy the facet or vertex data from the application data structure to an array of PEXlib packed data structures.
Here is an illustration of the stride model, using vertex
data:
In this example, you supply a pointer to the beginning of the structured array in the function call.
PEXOCCTriangleStrip(context, NULL, 20, vertex_data_pointer);
In this case, you set the OCC's data_model to PEXDataStride, and in addition to the OC Context values you had to set for the packed case, you also need to set vertex_stride and the offset members in the stride structure used above (in this case, vertex_coord_offset, vertex_normal_offset, vertex_color_offset, and vertex_fp_data_offset.) You do not need to set any offset members in the stride structure for data that you don't use. You tell PEXlib what data items it is to use by the facet/vertex attribute OCC members. With the stride interface, you must supply the offset for every data item that you specify is present in the facet/vertex attributes.
You handle facet data in exactly the same way, except you use different fields in the OC Context.
Some primitives, such as Fill Area Set and Polylines (Polyline Set) are defined by a nested list of vertices. Since you cannot work directly with a nested list of vertices, you use the PEXListOfVertexData, which looks like:
typedef struct { unsigned long count; PEXPointer vertices; } PEXListOfVertexData;
For each Fill Area Set Contour or Polyline in the set, you allocate one of these structures and fill it in with the number of points in that contour or line and a pointer to the first vertex in the list. Note that the type of the vertices pointer is PEXPointer, so you set this pointer to point to a structured array, just as in the non-nested case. The list of these PEXListOfVertexData structures must be contiguous and you pass the address of the first one in the vertex data argument of the primitive function call.
Related topics include:
For a list of all the related topics, see Programming Interface for Generating Output Commands.
You use this data interface style when your data is arranged in lists or arrays of points, colors, normals, etc. Each of these lists can reside anywhere in memory, since you supply a pointer to the start of each list. You also must specify the size of each element in the list by using the unpacked member of the OC Context.
When using this data format, as in this example, you need to set the data_model OCC member to PEXDataUnpacked and to set the vertex_coord_size, vertex_normal_size, vertex_color_size, and vertex_fp_data_size fields of the OCC. In addition, you pass pointers to each of the data arrays, four of them in this case, in the vertex data parameter of the primitive function call. To pass the four pointers, place them in the following structure and pass the address of the structure:
typedef struct { PEXPointer coords; PEXPointer colors; PEXPointer normals; PEXPointer edges; PEXPointer radii; PEXPointer axes; PEXPointer angles; PEXPointer fp_data; } PEXUnpackedVertexData;An example of using the unpacked data pointers:
PEXUnpackedVertexData verts; verts.coords = my_coords; verts.colors = my_colors; verts.normals = my_normals; verts.fp_data = my_fp_data; PEXOCCTriangleStrip(context, NULL, count, &verts);
When working with facet data, use the PEXUnpackedFacetData data structure. Some primitives, such as Fill Area Set and Polylines (Polyline Set) are defined by a nested list of vertices. Since you cannot work directly with a nested list of vertices, you use the PEXListOfVertexData data structure, which looks like:
typedef struct { unsigned long count; PEXPointer vertices; } PEXListOfVertexData;
For each Fill Area Set Contour or Polyline in the set, you
allocate one of these structures and fill it in with the
number of points in that contour or line and a pointer to
the first vertex in the list.
Note that the type of the vertices pointer is
PEXPointer,
so you set this pointer to point to a
PEXUnpackedVertex
data structure, just as in the non-nested case.
The list of these
PEXListOfVertexData
structures must be
contiguous and you pass the address of the first one in the
vertex data argument of the primitive function call.
For a list of related topics, see Programming Interface for Generating Output Commands.
The PEX output commands are designed so that the PEX implementation can often continue to process an OC with an error in it by using defaults or fall-back values. However, in some cases, it is not practical to define a reasonable fall-back value and so the PEX implementation stops processing OC's and generates an error, usually a BadPEXOutputCommand error.
Many BadPEXOutputCommand errors are very specific to the output command and are listed with the function. There are another set of errors that are common to a number of output commands and are not generally listed with each OC function.
BadPEXOutputCommand: Most cases are listed with each OC. Some of the causes common to many OC's are:
BadPEXStructurePermission: If you attempt to store an output command in a locked structure, the implementation generates this error.