XGL Device Pipeline Porting Guide
この本のみを検索
PDF 文書ファイルをダウンロードする

Handling Changes to Object State

4

This chapter describes how a device pipeline gets information about changes to XGL state. The chapter includes information on the following topics:
  • Changes to Context state and changes to objects associated with the Context
  • Changes to Device state
  • Design issues to think about when implementing state handling in a device pipeline

Imported image(30x36)

As you read this chapter, you will find it helpful to have access to the header files for the stroke groups and the header file defining the messages. These are:
  • StrokeGroup.h and StrokeGroup3d.h
  • Msg.h

State Changes and the Device Pipeline

The device pipelines are notified directly of Context attribute changes by the objectSet() and messageReceive() functions through the opsVec[] function array. Information about XGL object state is contained in the following device-independent objects:
  • Context and Context 3D objects store information about Context state.
  • Stroke group objects store information about certain multipolyline attributes and store the attribute value for these attributes as well.
  • The Context's view cache object stores information about items derived from the Context's view model attributes.
  • The set of Device objects store information about Device state.
The process of determining what attributes have changed and getting updated attribute values is described in the following sections.

Getting Attribute Values from the Context Object

The device pipelines are notified of Context attribute changes as soon as the application sets new attributes on the Context. When the application calls the API object set function to set a Context attribute value, the following events occur:
  1. The device-independent wrapper updates the Context object with the attribute changes, and the entire list of attribute types is processed.

  2. The current device pipeline is determined from the Context object.

  3. The wrapper calls the pipeline version of objectSet() through the XglDpCtx opsVec[XGLI_LI_OBJ_SET] entry and forwards the list of attribute types. Note that the attribute values are not passed to the pipeline in this list; the pipeline gets only the NULL-terminated list of attribute types.

To provide an objectSet() function for your pipeline, declare the function as a member of your pipeline XglDpCtx, and in the XglDpCtx's constructor, put a pointer to the function in the XGLI_LI_OBJ_SET entry of the opsVec[] array. The function pointer looks like this:
opsVec[XGLI_LI_OBJ_SET] = XGLI_OPS(XglDpCtx3dFb::objectSet);

The pipeline objectSet() function provides a switch statement for the attributes the pipeline is interested in. The switch statement can ignore attribute types that the pipeline isn't interested in and can combine attribute types that can be handled in the same way. The pipeline gets attribute values using Context interfaces. It can either update the hardware context immediately from within objectSet() or note that changes have occurred and update the hardware at a later time.
The following sample code shows a pipeline objectSet():

  //  
  // Example for the generic DP set function  
  //  
  XglDpCtx3dGx::objectSet(const Xgl_attribute *attr_type)  
  {  
      for(; *attr_type; attr_type++) {  
          switch (*attr_type) {  
  
            case XGL_CTX_LINE_COLOR: // set line color in DP  
              {  
                  Xgl_color *line_color =  
                         ctx->getCurrentStroke()->getColor();  
                  // send line color to hardware  
                  ...  
              }  
              break;  
  
                case ATTR_A:     // combine attributes  
                case ATTR_B:  
                case ATTR_C:  
                    do_something();  
              ...  
  
              case default:  
                // ignore attribute  
                break;  
          }  
      }  
  }  

See Context.h for the Context interfaces the pipeline can use to get Context attribute values. Note that if the device pipeline does not implement objectSet(), it will have to check the Context attributes at rendering time.
This might be an appropriate design for an LI-3 pipeline that is concerned with a small subset of attributes. However, implementing objectSet() is advisable for most pipelines for performance reasons.

When the Device Associated with a Context Is Changed

When the device-independent code calls the device pipeline's objectSet() to connect a Context to a Device, the device pipeline will receive only XGL_CTX_DEVICE in the attribute list. In this case, it is the device pipeline's responsibility to update all concerned Context attributes. To do this, the device pipeline can use the Context utility function getAttrTypeListAll(), which returns a pointer to a static list of all XGL Context attributes. The Context attribute list contains both 2D and 3D attributes.
An example of how a device pipeline can handle the objectSet() case for XGL_CTX_DEVICE is shown in the code fragment below.

  XglDpCtx3dGx::objectSet(const Xgl_attribute *attr_type)  
  {  
      for(; *attr_type; attr_type++) {  
          switch (*attr_type) {  
  
            case XGL_CTX_DEVICE: // new context attached  
              objectSet(ctx->getAttrTypeListAll());  
              break;  
  
              case...  
              ...  
          }  
      }  
  }  

Since getAttrTypeListAll() returns a list of all 2D and 3D Context attributes, it is recommended that the device pipeline create its own separate 2D and 3D Context attribute lists for optimum performance. The device pipeline could create static lists in its XglDpCtx[2,3]d pipeline classes.
If XGL_CTX_DEVICE is embedded in an xgl_object_set() call, as shown in the API call below, all Context attributes are updated with the API data included in the call before the device pipeline objectSet() is called. Thus, all device-independent Context attributes are up-to-date when a device pipeline receives XGL_CTX_DEVICE.

  xgl_object_set(ctx, XGL_CTX_LINE_COLOR, my_line_color,  
                 XGL_CTX_DEVICE, my_ras,  
                 XGL_CTX_NEW_FRAME_ACTION, my_new_frame_action,  
                 XGL_CTX_PLANE_MASK, -1,  
                 0);  

Getting Attribute Values from Objects Other Than the Context

The device pipeline is notified immediately of changes to objects other than the Context by the message passing mechanism. In XGL, when objects are instantiated, other objects can register interest in the new objects and become users of the objects. During program execution, when the used object's attributes change, the object sends a message to its users informing them of the change. For example, the Context becomes a user of the Line Pattern, Stroke Font, and Marker objects. When the Line Pattern changes, it sends a message about the change to the Context. When the Context receives an object message, it updates its data and forwards the message to the device pipeline by calling the XglDpCtx messageReceive() function through the opsVec[] XGLI_LI_MSG_RCV entry.
The pipeline messageReceive() function gets a pointer to an XGL object type and a message of type XglMsg. To provide a messageReceive() function, declare the function as a member of your pipeline XglDpCtx, and in the XglDpCtx's constructor, put a pointer to the function in the XGLI_LI_MSG_RCV entry of the opsVec[] array, as follows:
opsVec[XGLI_LI_MSG_RCV] = XGLI_OPS(XglDpCtx3dFb::messageReceive);

When you have done this, the messageReceive() function will always be called when there is a message for the XglDpCtx. The messageReceive() function will check the object type and message, and respond appropriately.
The pipeline can use the messageReceive() function to adjust to object changes. For example, if the hardware caches colors, the XglDpCtx can update the cached colors when messageReceive() receives a message that the color map changed. If the device caches a line pattern or light in its hardware, a
message about these objects indicates that the hardware context may need updating. The function can ignore messages that the pipeline is not concerned with.
The objects and messages are listed in Table 4-1. The default message, XGLI_MSG_STANDARD, simply indicates that an object has changed; it does not provide information about what changed or about what attribute caused the change. For the standard message type, the device pipeline can check individual attributes relevant to the object or reload the entire object into the hardware. See page 81 for more information on the view group messages.
Table 4-1
Object-MessageDescription
XGL_2D_CTX / XGL_3D_CTX
XGLI_MSG_VIEW_COORD_SYS

View group coordinate system changed, or push or pop of the
current coordinate system. You should check derived data.
XGLI_MSG_VIEW_CTX_ATTRView group Context attribute changes. This message corresponds to an API attribute that modifies derived data. You should check derived data.
XGL_LIGHT
XGLI_MSG_STANDARD

The Light object has changed. You may need to check derived data.
Update cached information regarding this Context attribute.
XGL_3D_CTX_LIGHT
XGL_LPAT
XGLI_MSG_STANDARD

The line pattern or edge pattern has changed. Update cached
information regarding these Context attributes.
XGL_CTX_LINE_PATTERN
XGL_CTX_EDGE_PATTERN
XGL_MARKER
XGLI_MSG_STANDARD

The user-defined marker has changed. Update cached information
regarding this Context attribute.
XGL_CTX_MARKER
Table 4-1
Object-MessageDescription
XGL_MEM_RAS
XGLI_MSG_STANDARD

Front or back surface fill pattern memory raster has changed.
Update cached information regarding these Context attributes.
XGL_CTX_RASTER_FPAT
XGL_CTX_SURF_FRONT_FPAT
XGL_3D_CTX_SURF_BACK_FPAT
XGL_SFONT_n
XGLI_MSG_STANDARD

Stroke Font object has changed. Update cached information
regarding this Context attribute.
XGL_CTX_SFONT_n
XGL_TMAP
XGLI_MSG_STANDARD



XGLI_MSG_TEXTURE_DESC

Front or back Texture Map object has changed. Update cached
information regarding these Context attributes.
XGL_3D_CTX_SURF_FRONT_TMAP
XGL_3D_CTX_SURF_BACK_TMAP

Texture Map descriptor has changed, and possibly the MipMap
Texture object has changed. You may need to recache the MIP map.
XGL_TRANS
XGLI_MSG_STANDARD

Global model transform, local model transform, or view transform
has changed. Check derived data. Update cached information
regarding these Context attributes.
XGL_CTX_GLOBAL_TRANS
XGL_CTX_LOCAL_MODEL_TRANS
XGL_CTX_VIEW_TRANS
In the 3D Context, the normal transform has changed. Check this
attribute.
XGL_3D_CTX_NORMAL_TRANS
XGL_WIN_RAS
XGLI_MSG_DEV_MULTIBUFFER

Multibuffering has been set on the device. Update cached
information regarding this Raster attribute.
XGL_WIN_RAS_MULTIBUFFER
Table 4-1
Object-MessageDescription
XGL_WIN_RAS / XGL_MEM_RAS
XGLI_MSG_DEV_COLOR

Color map has or depth pixel mapping has changed. Update
cached information regarding these Context attributes.
XGL_CTX_PLANE_MASK
XGL_CTX_MARKER_COLOR
XGL_CTX_LINE_COLOR
XGL_CTX_LINE_ALT_COLOR
XGL_CTX_EDGE_COLOR
XGL_CTX_EDGE_ALT_COLOR
XGL_CTX_STEXT_COLOR
XGL_CTX_SURF_FRONT_COLOR
XGL_3D_CTX_SURF_BACK_COLOR
XGL_CTX_BACKGROUND_COLOR
XGL_3D_CTX_SURF_FRONT_SPECULAR_COLOR
XGL_3D_CTX_SURF_BACK_SPECULAR_COLOR
XGL_3D_CTX_DEPTH_CUE_COLOR
XGL_CTX_RASTER_STIPPLE_COLOR
XGL_3D_CTX_LIGHT (XGL_LIGHT_COLOR)
Note that a message is sent both when the device is assigned a new
color map and when a change is made to an existing color map.
XGLI_MSG_DEV_DIMWindow width or height has changed, window raster has been
resized, or rect list has changed. You should check derived data.
XGLI_MSG_DEV_OTHERChanges in image buffer address, Z buffer address, source buffer, buffer display, buffer draw, buffer minimum delay, double buffer draw, number of buffers allocated, stereo mode. See the man pages for the Device attributes.
XGLI_MSG_RAS_CLIPRect list has changed. Update cached information regarding this Raster attribute.

XGL_RAS_RECT_LIST

The following sample code shows a pipeline messageReceive() function. This routine notes object changes, creates an attribute type list with attributes it is interested in, and sends the attribute type list to the pipeline objectSet() function. The pipeline objectSet() updates the hardware. This routine also sets a transformChanged flag so that it can point the opsVec renderer to the generic renderer. The generic renderer will check the transformChanged flag,
and, if necessary, it will check the view group using viewGrpItf->changedComposite(viewConcern) to see what changed in derived data. An alternate design for messageReceive() would be to update the hardware from within the function

  void XglDpCtx2dGx::messageReceive(XglObject* obj,  
                                          const XglMsg& msg)  
  {  
      switch (obj->getObjType()) {  
  
        case XGL_2D_CTX:  
        case XGL_3D_CTX:  
          if (msg.flag & (XGLI_MSG_VIEW_COORD_SYS |  
                              XGLI_MSG_VIEW_CTX_ATTR)) {  
                transformChanged = TRUE;  
                // Set generic renderers.  
          }  
          break;  
  
        case XGL_WIN_RAS:  
          if (obj == device) {  
              if (msg.flag & XGLI_MSG_DEV_COLOR) {  
              //  
              // Update cached colors and plane mask changes.  
              //  
                attrTypeList[0] = XGL_CTX_MARKER_COLOR;  
                attrTypeList[1] = XGL_CTX_LINE_COLOR;  
                attrTypeList[2] = XGL_CTX_LINE_ALT_COLOR;  
                attrTypeList[3] = XGL_CTX_SURF_FRONT_COLOR;  
                attrTypeList[4] = XGL_CTX_BACKGROUND_COLOR;  
                attrTypeList[5] = XGL_CTX_PLANE_MASK;  
                attrTypeList[6] = XGL_UNUSED;  
                objectSet((const Xgl_attribute*) attrTypeList);  
         }  
  
         if (msg.flag & XGLI_MSG_DEV_DIM) {  
                transformChanged = TRUE;  
                // Set generic renderers.  
         }  
  
         if (msg.flag & XGLI_MSG_DEV_OTHER) {  
                // Re-evaluate the number of buffers to render to  
                // based on bufferAllocated and XGL_CTX_RENDER_BUFFER  


                attrTypeList[0] = XGL_CTX_RENDER_BUFFER;  
                attrTypeList[1] = XGL_UNUSED;  
                objectSet((const Xgl_attribute*) attrTypeList);  
                // Set generic renderers.  
          }  
         }  
         break;  
  
        case XGL_LPAT:  
          if (obj == ctx->getLinePattern() ||  
                obj == ctx->getEdgePattern()) {  
                attrTypeList[0] = XGL_CTX_LINE_PATTERN;  
                attrTypeList[1] = XGL_UNUSED;  
                objectSet((const Xgl_attribute*) attrTypeList);  
           }  
          break;  
  
        case XGL_MARKER:  
          if (obj == (XglObject*)ctx->getMarker()) {  
                attrTypeList[0] = XGL_CTX_MARKER;  
                attrTypeList[1] = XGL_UNUSED;  
                objectSet((const Xgl_attribute*) attrTypeList);  
           }  
          break;  
  
        case XGL_TRANS:  
          if (obj == (XglObject*)ctx->getGlobalModelTrans() ||  
              obj == (XglObject*)ctx->getLocalModelTrans() ||  
              obj == (XglObject*)ctx->getViewTrans()) {  
  
                transformChanged = TRUE;  
                // Set generic renderers.  
           }  
          break;  
  }  

For additional information on object relationships, see the XGL Architecture Guide.

More on Device State Changes

In addition to passing device state changes to the pipeline via the message passing mechanism, the device-independent code notifies the device pipeline of device changes by calling the set...() functions defined in the XglDpDev class hierarchy. The XglDpDev functions enable the device to make device-specific changes. For example, in addition to the color map change message that is sent to the XglDpCtx, there are two virtual XglDpDev functions that are called when the color map or pixel mapping changes.
virtual void     setCmap(XglCmap*);
virtual void     setPixelMapping(const Xgl_usgn32[]);

See page 60 for information on the XglDpDev optional functions.

Handling Derived Data Changes

While objectSet() and messageReceive() enable the pipeline to keep track of the state of API attributes, the derived data facility is used to maintain data that are derived from the API attributes. The device pipeline is notified when derived data (view interface) changes by the message mechanism. When a derived data change occurs, the view object sends a message to the device pipeline by calling the XGLI_LI_MSG_RCV entry of the opsVec[] array, with the Context as the object type, and a message bitfield indicating what in derived data has changed.
Derived data changes that generate messages are set coordinate system, pop coordinate system, and any API Context attribute that could affect derived data. Device pipeline implementers may want to ignore the message flags and use checkchangedComposite() to see if any updating needs to be done whenever they receive a Context object message. The message flags for derived data changes are shown in Table 4-1 on page 76.
The device pipeline will set the view interface message in its messageReceive() function when the object type is XGL_2D_CTX or XGL_3D_CTX. Some example code to do this is shown below.

  // DP's receive message function. XGLI_LI_MSG_RCV slot  
  // in ops vector points to this:  
  
  void XglDpCtx2dGX::messageReceive(XglObject *obj,  
                                          const XglMsg& msg)  
  {  
      switch (obj->getObjType()) {  
        XGL_2D_CTX:  
          if (msg.flag & (XGLI_MSG_VIEW_CTX_ATTR |  
                          XGLI_MSG_VIEW_COORD_SYS)) {  
              // update DP's dervied data,  
              // check viewGrpItf->changedComposite(<view concerns>)  
          }  
          break;  
  
        ... //other message processing  
      }  
  }  

Information about derived data changes is computed in a lazy manner at a pipeline's request. See Chapter 6, "View Model Derived Data" for information on derived data.

Getting Stroke Attribute Values from the Stroke Group Object

The stroke group is the source from which the pipeline obtains the values for the line attributes, such as line color, during a multiPolyline() call. The idea behind the stroke group is to make the drawing of different strokes types as transparent as possible to a device pipeline that doesn't support all stroke primitives.
The primitives that may be rendered as multipolylines are lines, markers, text, edges, and hollow polygons. These primitives are considered to be stroke types. Since the same set of attributes (but different attribute values) applies to each of the stroke types when rendered as lines, the Context object maintains a stroke group object for each of the stroke types. For 2D, the stroke groups are line, marker, text, edge, and front surface. For 3D, the stroke groups are the 2D groups and the back surface group.
The stroke group object contains the actual attribute values for the stroke attributes. The stroke attributes are:
  • Antialiasing blend equation
  • Antialiasing filter width
  • Antialiasing filter shape
  • Alternate color
  • Cap
  • Color
  • Color selector
  • Join
  • Miter limit
  • Pattern
  • Style
  • Width scale factor
  • Flag mask
  • Expected flag mask
Most of the stroke attributes map to API attributes. However, flag mask and expected flag mask in StrokeGroup.h are specific to the stroke group object and depend on the stroke type; they are not API attributes and have no corresponding attribute type. For 3D rendering, the stroke group object is extended to include values for color interpolation and DC offset. Like flag mask and expected flag mask, DC offset in StrokeGroup3d.h does not map directly to an API attribute. See page 87 for information on flag mask and DC offset.

Example of Device Pipeline Use of Stroke Groups

Let's consider a device pipeline that cannot render text in hardware. In this situation, the text primitive will go through the software pipeline where it is tessellated into polylines. Before the polylines are handed to the device pipeline's LI-1 polyline renderer, the Context is told to activate the text stroke group. This activation sets the current stroke to the text stroke group and informs the device pipeline which stroke attributes have changed1. When the device pipeline reads the changed attributes out of the current stroke group, it

1. Only attributes that have actually changed betwee the old and new stroke groups will be sent to the device pipeline. For example, if the old stroke group was polylines and the line width was 1.0, changing the stroke group to text (whose line width is always 1.0) will not cause the line width attribute to be sent to the device pipeline.
gets the text attributes. For example, if the current line color is blue but the text color is green, the device pipeline will get the color green from the current stroke group. Figure 4-1 on page 84 illustrates this concept.

グラフィック

Figure 4-1

As long as text continues to be rendered, the text stroke group will remain the current stroke group. The current stroke group will change when either polylines are rendered, or another non-text stroke primitive falls back to the software pipeline for rendering.
Changes to stroke attributes are transmitted directly to the device pipeline. The only difference is that the device pipeline will see twice as many stroke attributes when anything other than the polyline stroke group is active. Thus, a device pipeline that fully accelerates text at LI-1 would see that XGL_CTX_STEXT_COLOR has changed, and a device pipeline that does not accelerate text at LI-1 would see that both XGL_CTX_STEXT_COLOR and XGL_CTX_LINE_COLOR have changed. It is necessary to pass the XGL_CTX_STEXT_COLOR attribute so that device pipelines which support text at LI-1 in some circumstances have a consistent view of the Context state.
See StrokeGroup.h and StrokeGroup3d.h for the interfaces a pipeline uses to obtain attribute values from the stroke group.

Rendering Multipolylines

Rendering polylines involves getting a pointer to the current stroke group and obtaining the attribute values that have changed from the stroke group. To indicate which stroke group will be used for rendering, the Context object provides a current stroke pointer that points to one of the stroke group objects. When the device pipeline receives a request to render a multipolyline, it gets the pointer to the current stroke group using the Context interface getCurrentStroke():
cur_stroke = ctx->getCurrentStroke()

Procedure for Getting Attribute Values for xgl_multipolyline()

For most primitives, new attribute values are obtained from the Context object. However, the difference between the attribute processing for an xgl_multipolyline() call and for other primitive rendering calls is that the values for the stroke attributes are obtained from the stroke group pointed to by the Context's current stroke pointer.
The steps for obtaining attribute values when rendering multipolylines are listed below.
  1. The pipeline gets the current stroke pointer using the Context interface

  cur_stroke = ctx->getCurrentStroke().

  1. The pipeline obtains the attribute values from the stroke group for changes in the line attributes. To get the line color, for example, the pipeline requests the line color with cur_stroke->getColor(). Values for attributes not in the stroke group are obtained from the Context, as in

ctx->getDepthCueMode().

  1. The pipeline loads the new values into hardware.


Note - The stroke group is designed to hide the actual type of stroke it is rendering from the pipeline. Normally, a device pipeline should get line group attributes from the XglStrokeGroup object for all multipolyline rendering unless the device pipeline can accelerate all primitives completely at LI-1 and will never call the software pipeline for tessellation. If a device pipeline does accelerate a stroke primitive (for example, it implements li1StrokeText()), the device pipeline can obtain the text attributes from the Context rather than from the stroke group. If you are absolutely sure that your pipeline does not fall back on the software pipeline for any of the stroke primitives (edges, text, markers, and hollow polygons) and that there is no chance of the stroke group being anything other than lineStrokeGroup, then your pipeline can get line group attributes directly from the Context. For primitives other than multiPolyline() that depend on the line attributes, the values for the line changes can be retrieved from the Context.

Procedure for Getting Attribute Values That Have Changed

The assignCurStrokeAs<prim>() functions are used by the software pipeline to change the current stroke group, and to call the device pipeline objectSet() function to inform the pipeline that certain stroke group attributes have changed.
Currently, when assignCurStrokeAs<prim>() is called, the device pipeline objectSet() function is also called notifying the pipeline of all changed line attributes. This means the device pipeline should load the current stroke attribute list for lines.
These objectSet() calls occurs in two different circumstances.
  • assignCurStrokeAs<prim>() is called by pipelines, changing the current stroke group (currentStrokeGroup).
  • Attributes corresponding to the current stroke group setting are changed by an objectSet() call. For example, if a text attribute, such as text color, changes while the current stroke group is pointing to the text group, objectSet() will be called after calling the software pipeline. This will call objectSet() through the XGLI_LI_OBJ_SET entry of the opsVec[] array sending the changed text attribute(s) as line attributes. In this
scenario, the device pipeline would receive an objectSet() call with a list of attribute types sent from the API, indicating which stroke attributes must be updated from the strokeGroup object.
If the device pipeline never needs stroke groups, it can process all the attributes directly from the Context and ignore the stroke group object. An intermediate approach is possible, since stroke groups only happen if the device pipeline calls the software pipeline for a particular case (stroke text, for example). In these cases, only the stroke groups still used by the device pipeline will generate an objectSet().

Flag Mask and Expected Flag Value

In XGL an application can provide flag information at each point of a primitive. This flag information determines whether specific line segments within the polyline are drawn. The stroke group flag mask and expected flag mask attributes are useful when the point type of the multipolyline being rendered has flag information.
If the point type has flag information, the pipeline ANDs the flag information in the vertex data with the flagMask from the stroke group and compares it to the expectedFlagValue from the stroke group. If they are equal, the line should be drawn; otherwise, the line should not be drawn.
Table 4-2 shows the flag information for the different stroke types.
Table 4-2
Stroke GroupFlag MaskExpected Flag Mask
Line stroke groupXGL_DRAW_EDGEXGL_DRAW_EDGE
Edge stroke groupXGL_DRAW_EDGE |
XGL_EDGE_IS_INTERNAL
XGL_DRAW_EDGE
Marker stroke groupNo bits setNo bits set
Front surface stroke groupXGL_EDGE_IS_INTERNALNo bits set
Back surface stroke groupXGL_EDGE_IS_INTERNALNo bits set
Text stroke groupNo bits setNo bits set
For example, the flag information for lines is XGL_DRAW_EDGE, whereas the flag information for edges could be XGL_DRAW_EDGE and/or XGL_EDGE_IS_INTERNAL. In the case of lines, the pipeline needs to determine whether XGL_DRAW_EDGE is set in the flag information before rendering the line. In the case of edges, the pipeline draws the edge when the XGL_DRAW_EDGE bit is set but not when XGL_EDGE_INTERNAL is set. Thus, when different stroke types are rendered as lines, the stroke group object provides getFlagMask() and getExpectedFlagValue() to make the dissimilarity in flags transparent to the device pipeline.
Example pseudocode to use these flags might be:

  Xgl_pt_flag_f3d       pt;  
  if (pt_type has flag) {  
       if ((pt.flag & cur_stroke->getFlagMask()) ==  
                cur_stroke->getExpectedFlagValue())  {  
           // Draw the line  
       }  


Note - At LI-1, since the point type can have flag data only when rendering lines (text and markers when rendered as lines cannot have point type with flag data), it is correct to assume that flagMask and expectedFlagValue are always the same (XGL_DRAW_EDGE) for li1MultiPolyline().

DC Offset

Some stroke types need to have the Z value adjusted either to ensure visual correctness or to respond to the setting of the API attribute XGL_3D_CTX_SURF_DC_OFFSET. The DC offset attribute is provided in StrokeGroup3d.h so that this is handled by the device pipeline. It determines if the Z of a line should be closer, unchanged, or farther than the original Z value of the line. The DC offset attribute can take on these enumerated values:
  • XGLI_DC_OFFSET_NONE - The DC offset attribute is set to this value for the line, marker, and text stroke groups. The pipeline does not need to adjust the Z value.
  • XGLI_DC_OFFSET_FRONT - The DC offset is set to this value when rendering edges as lines. It ensures that the edges appear on top of the polygon. The pipeline should subtract an offset from the Z component of each vertex of the multipolyline so that the line appears to be in front.
  • XGLI_DC_OFFSET_BACK - Used when hollow polygons are drawn as lines. This maps to the XGL API attribute XGL_3D_CTX_SURF_DC_OFFSET.
The DC offset values for the stroke groups are listed in Table 4-3.
Table 4-3
Stroke GroupDC Offset Value
Line stroke groupXGLI_DC_OFFSET_NONE
Edge stroke groupXGLI_DC_OFFSET_FRONT
Marker stroke groupXGLI_DC_OFFSET_NONE
Front surface stroke groupXGLI_DC_OFFSET_BACK if
XGL_3D_CTX_SURF_DC_OFFSET is TRUE
XGLI_DC_OFFSET_NONE if
XGL_3D_CTX_SURF_DC_OFFSET is FALSE
Back surface stroke groupXGLI_DC_OFFSET_NONE
Text stroke groupXGLI_DC_OFFSET_NONE
Thus, a pipeline adjusts the Z value according to value returned by the getDcOffset() function in the stroke group object. Note that the DC offset attribute is relevant only when Z-buffering is enabled.

Note - The software pipeline does not set the current stroke group to the edge stroke group, front-surface stroke group, or back-surface stroke group at the LI-1 layer. But, if a device falls back to software for text and markers, the current stroke can be either text/markers or line. But since the DC offset is not used by text/markers or line stroke groups, you can ignore the DC offset at li1MultiPolyline().

Design Issues

As you implement the processing of state changes, there are several design issues that you may want to consider. These issues are discussed briefly in the sections that follow.

Deciding to Reject a Primitive

The decision of whether the pipeline can render a primitive depends in part on the values of the attributes for the primitive. This means that the pipeline must process state information before it can conclude whether it can render the primitive.
A pipeline has two choices when evaluating attributes. It can abort processing if it finds an attribute it cannot accelerate (for example, if line width is greater than some value) or if the API information cannot be accelerated (for example, if the point type is homogeneous). The code fragment below shows an example of a pipeline calling the software pipeline to process wide lines.

  void DpCtx3dExampleDp::li1MultiPolyline(Xgl_bbox*    api_bbox,  
                                          Xgl_usgn32   api_num_plists,  
                                          Xgl_pt_list* api_pt_list)  
  {  
      const XglStrokeGroup3d* cur_stroke = ctx->getCurrentStroke();  
      if (cur_stroke->getWidthScaleFactor() >= 2.0) {  
           swp->li1MultiPolyline(api_bbox, api_num_plists,  
                                 api_pt_list);  
           return;  
      }  
      // Continue with li1MultiPolyline...  
  }  

Handling Context Switches

An application may be using any number of XGL Contexts. For example, it may use a different Context for each view of the geometry that it wants to display, or it may use different Contexts for areas of the window. It is the responsibility of the pipeline to update hardware state when the application switches the XGL Context that it is using to render.
One way to implement this might be to check which Context is being used to render when the primitive is entered. If the current Context is the same as the last Context, the function can continue other processing. If the Context is different from the last Context used, then the function should assume that the hardware state is invalid and take appropriate action. For example:

  if (dp_last_xgl_ctx != ctx) {  
       //  
       // Update derived data.  
       //  
       viewGrpItf->setComposite();  
  
       //  
       // Update all context attributes.  
       //  
       // All relevant attributes must be updated. The device  
      // pipelines objectSet() routine may be used.  
       //  
       objectSet(ctx->getAttrTypeListAll()); // DI utility list.  
  
       dp_last_xgl_ctx = ctx;  
  }  

How you handle updating your hardware after Context switches is an implementation decision left to you. Note that you may have to invalidate your hardware state when the Context changes only if you map all XGL Contexts to a single hardware context.

Partial Rendering of a Primitive

For the case in which a device pipeline calls the software pipeline to render some of the primitive's geometry and continues processing the rest of the primitive on its own, it is the device pipeline's responsibility to restore the hardware to the correct state before rendering the rest of the primitive. In other words, during the time that the software pipeline is processing its part of the geometry, the state of the hardware may change, and the device pipeline cannot rely on objectSet() to notify the pipeline of this change.
For example, during a multiSimplePolygon() call, if a device pipeline cannot render a complex polygon, it calls the software pipeline. At LI-2 or LI-3, the device pipeline must disable some attributes, such as model clipping or
MC to DC transformations, which are already done by the software pipeline at LI-1. When the control returns to the device pipeline to render the remaining simple polygons, the device pipeline may need to set up the hardware to render the polygons at LI-1 because the state of the hardware has changed. The device pipeline now needs the hardware to do model clipping and other operations, and has to set up the hardware accordingly.