|
| 以 PDF 格式下載這本書
Implementing Accelerated Primitives
4
- You should now be able to render pixels to your hardware using the RefDpCtx utility object. If pixel rendering is working, you are ready to implement accelerated renderers on your device. This chapter discusses the implementation of accelerated primitives. It also presents information on design issues to consider when implementing your pipeline
About Rendering and Attribute Handling
- Rendering and context state are handled by structures defined in the XglDpCtx classes and objects XglDpCtx2d and XglDpCtx3d. The XglDpCtx base class includes a dynamic array of function pointers to renderers and to functions that handle state setting. This array, called the opsVec array, is inherited by the device pipeline XglDpCtx2d and XglDpCtx3d objects. A portion of the default opsVec array in the base XglDpCtx3d class looks like this:
-
.....
opsVec[XGLI_LI1_MULTIMARKER] = XGLI_OPS(XglDpCtx3d::li1MultiMarker);
opsVec[XGLI_LI1_MULTIPOLYLINE] = XGLI_OPS(XglDpCtx3d::li1MultiPolyline);
.....
opsVec[XGLI_LI_OBJ_SET] = XGLI_OPS(XglDpCtx3d::objectSet);
opsVec[XGLI_LI_MSG_RCV] = XGLI_OPS(XglDpCtx3d::messageReceive);
|
- When the device pipeline is instantiated, its XglDpCtx object contains a set of opsVec array pointers specific to the device. In its version of the array, the device pipeline overrides some or all of the LI-1 and LI-2 entries to install
- function pointers to its own accelerated renderers. Renderers that are not overriden remain set to the default software pipeline renderers. The device pipeline must fill in pointers to LI-3 functions, since these routines are device dependent and not provided by XGL.
- At rendering time, the application primitive call is routed to the device pipeline by the XGL device-independent code. The device-independent code maps the C primitive call to a C++ internal call, and forwards the call and the application data to the device pipeline by calling the device pipeline opsVec entry for the primitive. If the device pipeline has installed a function pointer to one of its own renderers in the opsVec array, its renderer is called.
- An example of a device opsVec array is provided in DpCtx3dSkeleton.cc. In this file, the skeleton pipeline installs function pointers for the LI-1 and LI-3 required functions. The skeleton pipeline also includes function pointers for the required attribute handlers. For all other LI-1 and LI-2 renderers, the skeleton pipeline inherits the default array entries that point to software pipeline routines. A portion of the skeleton opsVec array is listed below.
-
// LI-1 Raster operations
opsVec[XGLI_LI1_NEW_FRAME] = XGLI_OPS(XglDpCtx3dSkeleton::li1NewFrame);
opsVec[XGLI_LI1_FLUSH] = XGLI_OPS(XglDpCtx3dSkeleton::li1Flush);
opsVec[XGLI_LI1_COPY_BUFFER]
=XGLI_OPS(XglDpCtx3dSkeleton::li1CopyBuffer);
.....
// LI3 Primitives - Required
opsVec[XGLI_LI3_MULTIDOT] = XGLI_OPS(XglDpCtx3dSkeleton::li3MultiDot);
opsVec[XGLI_LI3_VECTOR] = XGLI_OPS(XglDpCtx3dSkeleton::li3Vector);
opsVec[XGLI_LI3_MULTISPAN] = XGLI_OPS(XglDpCtx3dSkeleton::li3MultiSpan);
.....
// Attribute handlers - Required
opsVec[XGLI_LI_OBJ_SET] = XGLI_OPS(XglDpCtx3dSkeleton::objectSet);
opsVec[XGLI_LI_MSG_RCV] = XGLI_OPS(XglDpCtx3dSkeleton::receiveMessage);
|
- The device pipeline implementation of the attribute handling routines objectSet() and messageReceive() focuses on attributes that the pipeline is concerned with. The objectSet() routine handles attribute changes resulting from an application call to xgl_object_set(). The messageReceive() function handles attribute changes resulting from changes to XGL objects. Information on attribute changes is noted by the device-independent code and passed directly to the device pipeline through the opsVec array. See the skeleton pipeline DpCtx2dSkeleton.cc and DpCtx3dSkeleton.cc files for examples of these routines.
- The opsVec array is designed to minimize overhead in the device-independent code during a primitive call. The device pipeline is notified immediately of a primitive call or attribute changes.
Rendering in the Skeleton Pipeline
- The skeleton graphics handler provides example accelerated pipelines for 3D LI-1 multipolylines and for 2D LI-2 polygons. The renderers reside in the files Skeleton2dLi2Pgon.cc and Skeleton3dLi1Mpl.cc. Each skeleton pipeline renderer is designed as a set that includes these routines:
-
- A generic routine that evaluates incoming data and determines whether acceleration is possible
- A fast renderer that does a quick test of the application arguments and then sends application point data to the hardware
- Each generic routine does the following:
-
- Checks the application data and handles other changes that the pipeline needs to be aware of, such as context changes.
- Determines the current attribute settings for the attributes that the pipeline is concerned with.
- Sets the opsVec[] entry to the default software pipeline routine or to the fast renderer, depending on the attribute settings. In some cases, the routine calls the software pipeline directly.
- The device pipeline can set opsVec entries at object creation or at any time during program execution. Installing opsVec array entries during program execution is usually a result of attribute changes and can be done from the objectSet() routine. As an example, the skeleton pipeline sets opsVec array entries by doing the following:
-
- At device pipeline initialization, the skeleton pipeline initializes the opsVec array with static renderers for the LI-1 and LI-3 routines.
- When a primitive call occurs, the skeleton pipeline generic renderer determines whether acceleration is possible. It checks the following:
-
- If the application data (the point type) cannot be accelerated, the software pipeline is called directly to do the operations at that loadable interface level, but the opsVec entry remains set to the generic pipeline. If the point type can be accelerated, the generic renderer continues by checking the current attribute settings.
- If the current attribute settings can be accelerated, the generic renderer sets the fast renderer in the opsVec array and then calls it. If the current attribute settings cannot be accelerated, the generic renderer sets the default software pipeline renderer in the opsVec array and then calls it.
-
- When attributes change, if the skeleton pipeline is concerned with the changed attributes, the objectSet() routine sends the new values to the hardware and resets the generic renderer in the opsVec so that it will be called to re-evaluate whether acceleration is possible the next time a primitive is called.
- In your implementation, you will set the opsVec array entries to your accelerated renderers. For some primitives, you may want to have a pair of renderers as shown in the skeleton pipeline. For other renderers, you may need a family of renderers to handle optimized cases of attributes or point types.
Steps for Implementing the Skeleton Renderers
- To use the skeleton pipelines, you must add code to send data to your hardware. Depending on your hardware and implementation, you may also need to modify these routines in other ways so that they correspond to your hardware. In addition, you need to modify the DpCtxSkeleton files to set up attribute handling and rendering for your device.
- The sections that follow describe the implementation of the skeleton renderers in detail. If you plan to implement accelerated rendering at the LI-1 layer, read the section on LI-1 multipolyline on page 35; if your hardware is suited for LI-2 acceleration, read the section on LI-2 polygon on page 29. How you modify the skeleton code will vary depending on your implementation.
· Implementing the 2D Polygon Renderer
- The Skeleton2dLi2Pgon.cc file provides an example of a simple 2D polygon renderer implemented at the LI-2 layer. The file contains two routines:
-
- A generic renderer, li2GeneralPolygon, that determines whether acceleration is possible. li2GeneralPolygon is the entry point for the device pipeline polygon renderer at LI-2. A device pipeline for a device that implements polygon acceleration at the LI-2 level will provide this routine.
- A fast renderer, li2FastGeneralPolygon, that sends data to the hardware given certain point types and attribute values.
- The following steps take you through the sections of these routines in detail and examine the kinds of modifications you might need to make to implement them for your hardware.
· Step 1: Modify the generic renderer.
- The generic polygon renderer, li2GeneralPolygon, checks for point type, context, primitive, and attribute changes. If no changes have occurred, the routine sets the fast renderer in the opsVec array and calls the opsVec[] entry to send data to the hardware.
-
Note - At the LI-2 level, data is given to device pipelines under the control of the XglPrimData object. At LI-2, the software pipeline has performed LI-1 processing and stored the API data internally in XglLevel format. The LI-2 device pipeline must extract point and facet data from the XglLevel object. The skeleton pipeline provides an example of the use of the XglLevel methods. For more information on how the software pipeline stores data and on the methods the device pipeline can use to extract this data, see the XGL Device Pipeline Porting Guide.
- The code for the initial section of li2GeneralPolygon is listed below. To implement li2GeneralPolygon for your hardware, you may need to modify one or more statements in the initial section of the routine. These changes are listed following the code, and the numbers to the left of the code sample correspond to the list items. Note that some of the actual code comments in li2GeneralPolygon have been omitted in this listing.
-
-
void XglDpCtx2dSkeleton::li2GeneralPolygon(XglPrimData* pd)
{
XglLevel* level = pd->getCurrentLevelData();
Xgli_point_list* pt_list = level->getPointLists();
Xgli_facet_list* facet_lists = level->getFacetList();
-

// Check point list changes.
if (!pt_list) {
return;
} else if (pt_list->pt_type != XGL_PT_FLAG_F2D ||
(facet_lists && facet_lists->facet_type != XGL_FACET_NONE)) {
swp->li2GeneralPolygon(pd);
return;
}
-

// Check for context change.
if (dpMgr->lastDpCtx != this) {
updateContext();
}
-

// Determine whether the primitive has changed.
if (lastPrim != XGLI_LI2_POLYGON) {
if (ctx->getSurfFrontCOlorSelector() ==
XGL_SURF_COLOR_CONTEXT) {
// Set Context surface front color into hardware
}
lastPrim = XGLI_LI2_POLYGON;
}
// Lock window.
WIN_LOCK(drawable) ;
if (drawable->windowIsObscured()) {
WIN_UNLOCK(drawable) ;
return; // Window is obscured; don't render
}
-

Xgl_boolean accelerate =
(surfFrontFillStyle == XGL_SURF_FILL_SOLID) &&
// Pattern is dependent on style. This example only
// accelerates style XGL_SURF_FILL_SOLID.
// FpatPosition is dependent on pattern.
// ctx->getSurfFrontFpat():
// ctx->getSurfFrontFpatPosition():
-
-
(ctx->getRop() == XGL_ROP_SRC) &&
(ctx->getPlaneMask() == (Xgl_usgn32)-1) &&
(ctx->getSurfEdgeFlag() == FALSE) &&
(ctx->getSurfInteriorRule() == XGL_EVEN_ODD) &&
(ctx->getSurfFrontColorSelector() == XGL_SURF_COLOR_CONTEXT) ;
// Antialiasing support on 2D Contexts is device dependent
// (ctx->getSurfAaBlendEq() == XGL_BLEND_NONE) &&
// (ctx->getSurfAaFilterShape() == XGL_FILTER_GAUSSIAN) &&
// (ctx->getSurfAaFilterWidth() == 1) &&
-
- Statement 1 in li2GeneralPolygon specifies which API data types are accelerated. The skeleton pipeline accelerates rendering if the point type is XGL_PT_FLAG_F2D. If a facet list is present, the facet type must be XGL_FACET_NONE. In any other case, the routine calls the software pipeline to perform LI-2 operations. The software pipeline may call back the device pipeline at the LI-3 level.
For your implementation, consider what point types and facet types the hardware can accelerate. Then modify statement 1 as needed so that your pipeline corresponds with the capabilities of your hardware. For information on the complete set of XGL data types, see the XGL Reference Manual.
- Statement 2 determines whether a context switch has occurred. If the XGL Context that the application is using has changed, the updateContext() routine in XglDpCtx2dSkeleton is called to update the view group interface object and the Context attributes.
If your hardware has only one hardware context, use this statement to keep track of context switches. If your hardware has multiple hardware contexts, you may want to associate each hardware context with an XGL Context. In this case, you do not need to check for context changes. Note, however, that some applications may define many XGL Context objects, so you may want to monitor context changes even if your hardware has multiple contexts.
- Statement 3 determines whether the primitive has changed. Because context state may be different for each primitive, you may want to check context state for some attributes. For example, you may want to get the Context color for the current primitive and set it on the hardware before rendering.
-
- Statement 4 checks the current attribute settings to evaluate whether to use the skeleton pipeline accelerated renderer or fall back to the software pipeline. The skeleton pipeline accelerates rendering if the surface front fill style is solid, and the ROP, plane mask, surface edge flag, surface interior rule, and surface front color selector are set to the default values.
Modify this section if you implement other values for these attributes. For example, if your hardware handles fill styles, your pipeline should check the fill attributes. If your hardware handles the ROP mode XOR, your renderer should check the ROP attributes.
- The last section of li2GeneralPolygon sets the opsVec entry to li2FastGeneralPolygon if acceleration is possible, or calls the software pipeline if acceleration is not possible. The opsVecDiDefault routine reinstalls the software pipeline as the default opsVec entry. The opsVec entry remains set to the software pipeline or the fast renderer until an attribute changes. At that time, the objectSet routine sends the attribute changes to the hardware and reinstalls the generic li2GeneralPolygon in the opsVec array. After an attribute change, the next time rendering occurs, the generic renderer evaluates changes and determines which renderer to call. You do not need to modify this code for your device pipeline.
-
-
if (!accelerate) {
// Unlock window.
WIN_UNLOCK(drawable);
// Set opsVec[] to default renderer.
opsVec[lastPrim] = opsVecDiDefault[lastPrim];
// Call renderer though opsVec[]
(this->*((void(XglDpCtx2d::*)(XglPrimData*))
(opsVec[lastPrim])
)
)(pd);
return;
}
// Acceleration is possible. Set opsVec[] to fast renderer.
opsVec[lastPrim] =
XGLI_OPS(XglDpCtx2dSkeleton::li2FastGeneralPolygon);
// Call renderer though opsVec[]
(this->*((void(XglDpCtx2dSkeleton::*)(XglPrimData*))
-
-
(opsVec[lastPrim])
)
)(pd);
// Unlock window.
WIN_UNLOCK(drawable);
-
Note - In your implementation, you can call the software pipeline directly as swp->li2GeneralPolygon(pd) rather than through the opsVec array.
· Step 2: Modify the fast renderer.
- The li2FastGeneralPolygon routine first tests to verify that nothing has changed. The test checks that the point list is valid, that the context and the facet type have not changed, and that the last primitive was sent from the li2GeneralPolygon group of renderers. If something has changed, the routine sets the generic renderer and calls it directly. Otherwise, it sends data to the hardware.
- In your implementation, add code in the fast renderer to send data to the hardware. Note that the skeleton renderer does not handle surface edges. An example of how to access LI-2 edge flag data in a renderer that supports edges is provided in the Skeleton2dLi2Pgon.cc comments.
-
-
void XglDpCtx2dSkeleton::li2FastGeneralPolygon(XglPrimData* pd)
{
XglLevel* level = pd->getCurrentLevelData();
Xgli_point_list* pt_list = level->getPointLists();
Xgli_facet_list* facet_lists = level->getFacetList();
Xgl_facet_type ftype = (facet_lists) ? facet_lists->facet_type
: XGL_FACET_NONE;
XglDrawable* localDrawable = this->drawable;
WIN_LOCK(localDrawable);
if (!pt_list | (int)dpMgr->lastDpCtx - (int)this |
ftype - lastFacetTypeInfo.facet_type |
XGLI_LI2_POLYGON - lastPrim) {
WIN_UNLOCK(localDrawable);
-
-
// Set default generic renderer, then execute.
opsVec[XGLI_LI2_POLYGON] =
XGLI_OPS(XglDpCtx2dSkeleton::li2GeneralPolygon);
li2GeneralPolygon(pd);
return;
}
Xgl_pt_i2d *pts;
Xgl_sgn32 num_pts; // Number of points
Xgl_usgn32 num_pl = level->getNumPointLists();
Xgl_sgn32 pt_size = pt_list->geom_ptr.step_size;
for (Xgl_usgn32 i = 0; i < num_pl; i++) {
num_pts = pt_list[i].current_num_points;
// Skip point lists with less than three points.
if (num_pts < 3) {
continue;
}
pts = (Xgl_pt_i2d*)pt_list[i].geom_ptr.base_ptr;
flags = (Xgl_usgn32*)pt_list[i].flag_ptr.base_ptr;
// my_hw = BEGINNING_OF_POLYGON
for (Xgl_usgn32 j = 0; j < num_pts; j++) {
// Pass data to hardware.
// my_hw_x = pts->x;
// my_hw_y = pts->y;
XGLI_INCR(flags, Xgl_usgn32*, flag_size);
XGLI_INCR(pts, Xgl_pt_i2d*, pt_size);
} // end for(j)
} // end for(i)
// Unlock window
WIN_UNLOCK(localDrawable);
}
· Step 3: Update DpCtx2dSkeleton.
- Before your implementation of 2D polygon rendering is complete, you must modify the DpCtx2dSkeleton.cc file as follows:
-
- Modify the routine to add your renderer. You can uncomment the following line in objectSet():
-
// opsVec[XGLI_LI2_POLYGON = XGLI_OPS(XglDpCtx2dSkeleton::li2GeneralPolygon);
|
-
- Add code to the objectSet() routine to update your hardware context for all the XGL Context attributes that your pipeline is concerned with.
The routine retrieves the current attribute values and sends them to the hardware. It also sets a flag, li2_generalpolygon_change_renderer, that indicates whether the generic renderer should be reinstalled.
- When you have made these changes, your implementation of the skeleton 2D polygon renderers is complete. Use the Denizen test suite to test your implementation.
· Implementing the 3D Multipolyline Renderer
- The Skeleton3dLi1Mpl.cc file provides an example of a simple 3D line renderer implemented at the LI-1 layer. The file contains three routines:
-
- A generic renderer, li1MultiPolyline, which determines whether acceleration is possible. li1MultiPolyline is the entry point for the device pipeline line renderer at LI-1. A device pipeline for a device that implements line acceleration at the LI-1 level will provide this routine.
- A fast renderer, li1MplineFast, that sends data to the hardware given certain point types and attribute values.
- A 3D model clipping routine, li1MplineMC, that model clips the data and calls the fast renderer to send the data to the hardware.
- The following steps take you through the sections of these routines in detail and examine the kinds of modifications you might need to make to implement them for your hardware.
· Step 1: Modify the generic renderer.
- The generic renderer, li1MultiPolyline, checks for point type, context, primitive, and attribute changes. If no changes have occurred, the routine sets the fast renderer in the opsVec array and calls the opsVec[] entry to send data to the hardware.
- The code for the initial section of li1MultiPolyline is listed below. To implement this routine for your hardware, you may need to modify one or more statements in the initial section of the routine. These changes are listed following the code, and the numbers to the left of the code sample correspond to the list items. Note that some of the code comments in li1MultiPolyline have been omitted in this listing.
-
-
void XglDpCtx3dSkeleton::li1MultiPolyline(Xgl_bbox* api_bbox,
Xgl_usgn32 api_num_plists,
Xgl_pt_list* api_pt_list)
{
// Determine whether API data can be accelerated.
if (!api_pt_list) {
return;
} else if (api_pt_list->pt_type != XGL_PT_F3D) {
swp->li1MultiPolyline(api_bbox, api_num_plists, api_pt_list);
return;
}
-

-
-
// Create a local copy of the point type.
Xgl_pt_type pt_type = api_pt_list->pt_type;
// Determine whether the point type changed. If so,
// update point type information.
// The XgliUtPtTypeInfo utility saves information about
// the point type that the fast renderer can use.
if (lastPtTypeInfo.pt_type != pt_type) {
XgliUtPtTypeInfo(pt_type, &lastPtTypeInfo);
lastPtTypeInfo.pt_type = pt_type;
}
-

// Check for context change.
if (dpMgr->lastDpCtx != this) {
updateContext();
}
-

// Determine whether the primitive has changed.
if (lastPrim != XGLI_LI1_MULTIPOLYLINE) {
-
-
if ((ctx->getCurrentStroke()->getColorSelector() ==
XGL_LINE_COLOR_CONTEXT)) {
// Set Context line color into hardware.
}
// Update other attributes that may have changed.
lastPrim = XGLI_LI1_MULTIPOLYLINE;
}
// Lock window.
WIN_LOCK(drawable) ;
if (drawable->windowIsObscured()) {
WIN_UNLOCK(drawable) ;
return; // Window is obscured.
}
// Determine whether the transform changed.
if (transformsChanged ||
viewGrpItf->changedComposite(li1StrokeViewConcern)) {
updateTransforms();
}
// Determine whether the window clip list changed.
// If so, update the hardware clip list using the DpCtxSkeleton
// sharedUpdateLi1Cliplist() routine.
// Hardware clip list updating must happen while in WIN_LOCK().
if (drawable->clipChanged()) {
// Update window clip list related changes.
sharedUpdateLi1Cliplist();
}
-

Xgl_boolean accelerate =
(lineStyle == XGL_LINE_SOLID) &&
(ctx->getRop() == XGL_ROP_SRC) &&
(ctx->getPlaneMask() == (Xgl_usgn32)-1) &&
(ctx->getDepthCueMode() == XGL_DEPTH_CUE_OFF) &&
(cur_stroke->getAaBlendEq() == XGL_BLEND_NONE)&&
(cur_stroke->getAaFilterShape() == XGL_FILTER_GAUSSIAN) &&
(cur_stroke->getAaFilterWidth() == 1) &&
// getPattern(): Pattern is dependent on style. This
// example only accelerates style XGL_LINE_SOLID.
// getAltColor(): AltColor is dependent on pattern.
(cur_stroke->getCap() == XGL_CAP_BUTT) &&
-
-
(cur_stroke->getJoin() == XGL_JOIN_DEVICE) &&
(cur_stroke->getColorInterp() == FALSE) &&
(cur_stroke->getColorSelector() == XGL_LINE_COLOR_CONTEXT) &&
(cur_stroke->getWidthScaleFactor() <= 1.0);
-
- Statement 1 in li1MultiPolyline specifies which API data types are accelerated. The skeleton pipeline line renderer accelerates rendering if the point type is XGL_PT_F3D. For any other point type, the routine calls the software pipeline to perform LI-1 operations.
For your implementation, consider what point types your hardware can accelerate. Then modify statement 1 as needed so that your pipeline corresponds with the capabilities of your hardware. For information on the complete set of XGL data types, see the XGL Reference Manual.
- Statement 2 determines whether a context switch has occurred. If the XGL Context that the application is using has changed, the updateContext() routine in XglDpCtx3dSkeleton is called to update the view group interface object and the Context attributes.
If your hardware has only one hardware context, use this statement to keep track of context switches. If your hardware has multiple hardware contexts, you may want to associate a hardware context with an XGL Context. In this case, you do not need to check for context changes. Note, however, that some applications may define many XGL Context objects, so you may want to monitor context changes even if your hardware has multiple hardware contexts.
- Statement 3 determines whether the primitive has changed. Because context state may be different for each primitive, you may want to check context state for some attributes. For example, you may want to get the Context color for the current primitive.
- The next section of li1MultiPolyline checks the current attribute settings as part of determining whether to use the skeleton pipeline accelerated renderer or fall back to the software pipeline. The skeleton pipeline accelerates rendering when the attributes are set to the default values.
Modify this section if you implement other values for these attributes. For example, if your hardware handles line patterns, your pipeline will be concerned with the line pattern attributes.
- The skeleton pipeline accelerates lines if the hardware has a hardware Z buffer. If Z buffering is enabled and the hardware does not have a hardware Z buffer, there is no acceleration.
-
-
if (ctx->getHlhsrMode() == XGL_HLHSR_Z_BUFFER &&
!dpMgr->hwZBuffer) {
accelerate = FALSE;
}
- The last section of li1MultiPolyline sets the opsVec entry to the fast renderer, if acceleration is possible, or calls the software pipeline if acceleration is not possible. The routine also determines whether model clipping is enabled. If so, it sets the opsVec entry to the li1MplineMC routine, which uses the XgliUtModelClipMpline utility to model clip the application data and calls li1MplineRenderer to perform the rendering. If your hardware doesn't handle model clipping, you can use the XgliUtModelClipMpline utility to do model clipping in software. The utility returns model clipped data.
- The opsVec entry remains set to the software pipeline or the fast renderer until an attribute changes. At that time, the objectSet routine sends the attribute changes to the hardware and reinstalls the generic renderer in the opsVec array. After an attribute change, the next time rendering occurs, the generic renderer again tests for changes, and determines which renderer to call.
-
-
if (!accelerate) {
WIN_UNLOCK(drawable);
// Set opsVec[] to default renderer.
opsVec[lastPrim] = opsVecDiDefault[lastPrim];
// Call renderer though opsVec[]
(this->*((void(XglDpCtx3d::*)
(SKELETON_PROTOTYPE_ARGS_MPLINE))
(opsVec[lastPrim])
)
)(api_bbox, api_num_plists, api_pt_list);
return;
}
// Acceleration is possible. Set opsVec[] to fast renderer.
li1MplineRenderer = XglDpCtx3dSkeleton::li1MplineFast;
-
-
// Model clipping?
if (ctx->getModelClipPlaneNum())
opsVec[lastPrim] - XGLI_OPS(XglDpCtx3dSkeleton::li1MplineMC);
else
opsVec[lastPrim] = XGLI_OPS(li1MplineRenderer);
// Call renderer though opsVec[]
(this->*((void(XglDpCtx3dSkeleton::*)
(SKELETON_PROTOTYPE_ARGS_MPLINE))
(opsVec[lastPrim])
)
)(api_bbox, api_num_plists, api_pt_list);
WIN_UNLOCK(drawable) ;
}
-
Note - In your implementation, you can call the software pipeline directly as swp->li1MultiPolyline() rather than through the opsVec array.
· Step 2: Modify the fast renderer.
- The li1FastMultiPolyline routine tests to verify that nothing has changed. The test determines whether the point list is valid, the context and the facet type have not changed, and the last primitive was from the li1MultiPolyline group of renderers. If something has changed, the routine sets the generic renderer and calls it directly. Otherwise, it sends data to the hardware.
- In your implementation, add code in the fast renderer to send the application data to the hardware.
-
-
void XglDpCtx3dSkeleton::li1MplineFast (Xgl_bbox* api_bbox,
Xgl_usgn32 api_num_plists,
Xgl_pt_list* api_pt_list)
{
XglDrawable* localDrawable = this->drawable;
WIN_LOCK(localDrawable);
if (!api_pt_list |
(int)dpMgr->lastDpCtx - (int)this |
api_pt_list->pt_type - lastPtTypeInfo.pt_type |
-
-
transformsChanged |
localDrawable->modifChanged() |
XGLI_LI1_MULTIPOLYLINE - lastPrim) {
// If acceleration not possible, unlock window
WIN_UNLOCK(localDrawable);
// Set default generic renderer (slower), then execute.
opsVec[XGLI_LI1_MULTIPOLYLINE] =
XGLI_OPS(XglDpCtx3dSkeleton::li1MultiPolyline);
li1MultiPolyline(api_bbox, api_num_plists, api_pt_list);
return;
}
float *pts;
Xgl_sgn32 num_pts;
Xgl_sgn32 pt_size = lastPtTypeInfo.pt_size;
for (Xgl_usgn32 i = 0; i < api_num_plists; i++) {
num_pts = api_pt_list[i].num_pts;
if (num_pts < 2) {
continue;
}
pts = (float*)api_pt_list[i].pts.f3d;
// my_hw = BEGINNING_OF_MULTIPOLYLINE
for (Xgl_usgn32 j = 0; j < num_pts; j++) {
// Pass data to hardware here.
// my_hw_x = pts[0]; // x
// my_hw_y = pts[1]; // y
// my_hw_z = pts[2]; // z
XGLI_INCR(pts, float*, pt_size);
} // end for(j)
} // end for(i)
WIN_UNLOCK(localDrawable);
}
· Step 3: Update DpCtx3dSkeleton.
- Before your implementation of 3D line rendering is complete, you must modify the DpCtx3dSkeleton.cc file as follows:
-
- Modify the routine to add your renderer. You can simply uncomment the following line in the skeleton pipeline objectSet():
-
// opsVec[XGLI_LI1_MULTIPOLYLINE =
XGLI_OPS(XglDpCtx3dSkeleton::li1MultiPolyline);
|
-
- Add code to the objectSet() routine to update your hardware context for all the XGL Context attributes that your pipeline is concerned with.
The routine retrieves the current attribute values and sends them to the hardware. It also sets a flag, li1_multipolyline_change_renderer, that indicates whether the generic renderer should be reinstalled.
- Add code to the updateTransforms() routine to send transform information to the hardware when transforms change.
- Add code to sharedUpdateLi1Cliplist() in DpCtxSkeleton.cc to handle hardware clipping.
- When you have made these changes, your implementation of the skeleton 3D polygon renderers is complete. Use the Denizen test suite to test your implementation.
|
|