XGL Device Pipeline Porting Guide
只搜寻这本书
以 PDF 格式下载本书

Pipeline Interface Classes

3

This chapter presents information on the classes and objects that connect XGL device-independent code with the device pipeline code. The following topics are covered:
  • Deriving the required device pipeline classes
  • Pipeline naming conventions and versioning
  • Providing renderers optimized for performance-critical primitives
  • Description of required and optional device-dependent functions
  • Using XGL for backing store support

Imported image(30x36)

As you read this chapter, you will find it helpful to have access to the header files for the device pipeline classes. These files are:
  • PipeLib.h and DpLib.h
  • DpMgr.h
  • DpDev.h, DpDevRaster.h, DpDevWinRas.h, and DpDevMemRas.h
  • DpCtx2d.h and DpCtx3d.h

Note - In XGL the term device refers to both the physical hardware device and the XGL API Device object. The API Device object is an abstraction of the graphics display device. Internally, the Device object consists of two objects: a device-independent object and a device-dependent object. For more information on the internal components of the API Device object, see the XGL Architecture Guide.

Overview of the Pipeline Interface Classes

The XGL architecture has a device-independent component and a device-dependent component. Because the device-independent component of XGL must interact smoothly with the device pipeline, XGL provides a set of classes that allow XGL to pass information to and from the device pipeline. Setting up the basic pipeline framework is one of the primary tasks in writing a device pipeline.
A pipeline implementation must derive five classes from four different class hierarchies that form the basic framework of a device pipeline. The pipeline-derived classes are the following:
  • Device pipeline library (DpLib) class
  • Device pipeline manager (DpMgr) class
  • Device pipeline device (DpDev) class
  • Device pipeline context (DpCtx2d and DpCtx3d) class
Objects instantiated from these pipeline interface classes provide the functionality that the XGL device-independent code requires. Figure 3-1 on page 27 shows the XGL-supplied class header files, header files derived by the pipeline implementation, and the pipeline objects that are instantiated.
Each of the device pipeline derived classes contains functions that you must implement. In some cases, the functions simply create the next level of the hierarchy; in other cases, there are API-level functions or attributes that the pipeline must support. Several classes also include optional functions for operations that depend on the hardware.
In addition to providing the required classes and functionality, you must include in your library a function called xgli_create_PipeLib(), which creates the XglDpLib object that represents the pipeline library. You must also name your pipeline appropriately so that XGL can find and load the pipeline object.

图形

Figure 3-1

Naming Your Device Pipeline

An XGL device pipeline must be named according to the following convention:
xgl<COMPANY NAME><device name>.so.<major version>

where:
  • <COMPANY NAME> is a 4-letter capitalized abbreviation for the company that implements the device pipeline. For example, Sun uses its stock symbol SUNW for company name.
  • <device name> is the abbreviated name of the device, which should be an abbreviated form of the name of the corresponding kernel device driver located in the /dev directory.
  • <major version> is the major release number of the DDK associated with the particular release of XGL that is compatible with this device pipeline. For example, a Sun Microsystems Cg6 device pipeline with a major version number of 4 is named xglSUNWcg6.so.4. The DDK major version number can be found in the header file xgli/DdkVersion.h.
The name of the pipeline is defined in the Makefile located in the device pipeline build area. The Makefile macro LIB_NAME must be set to the pipeline name.
When XGL attempts to load a pipeline, it issues a system call that returns the pipeline name for the active device. For more information on how XGL loads a device pipeline, see "How a Device Pipeline Is Loaded" on page 52.

About Versioning

The XGL device-independent library (libxgl.so) dynamically loads device pipeline modules at runtime; therefore, a versioning scheme is required to ensure that the device-independent library and the pipeline that it loads are compatible. The versioning scheme is implemented both as part of the XGL device-independent library and as part of the Driver Developer Kit (DDK).
The DDK contains header files that define the interfaces between the device-independent XGL library and the dynamically loaded pipeline modules. The device-independent library and the DDK have a version number that is called the DDK version number. This version number, which contains both major and minor parts, is defined by two macro definitions in the file xgli/DdkVersion.h. The macro definitions for the current release are:
#define XGLI_DDK_MAJOR_VERSION  4
#define XGLI_DDK_MINOR_VERSION  1

Every XGL device pipeline must include the DdkVersion.h header file in order to use the versioning information.

Versioning Rules

Each release of XGL is accompanied by a corresponding release of the DDK containing files used to build the device-independent XGL library and the reference device pipelines. Independent Hardware Vendors (IHV's) use the DDK to build a device handler that is compatible with the device-independent XGL library in that release.
The DDK version number is unrelated to the XGL API library version number. For example, the 3 in libxgl.so.3 is the version number of the XGL API release. It is not related to the internal DDK majorVersion number. IHV's supplying XGL device pipelines must conform to the following versioning rules:
  1. The DDK majorVersion (defined in xgli/DdkVersion.h) used to build the device pipeline is included in the file name of the device pipeline, such as, xglSUNWcg6.so.4, where the 4 is the same as majorVersion. The convention used to name a device pipeline is:

    xgl<COMPANY NAME><device name>.so.<majorVersion>

  1. The device-independent XGL library is stamped internally with both the DDK major and minor version numbers of the DDK used to build it. The device-independent XGL library will never load a pipeline with a DDK majorVersion greater than its own. For example, libxgl.so with DDK internal version number 3 will not load a pipeline named xglSUNWcg6.so.4.

  2. The device-independent XGL library loads a device pipeline with a DDK majorVersion less than its own DDK majorVersion only if the XGL device-independent library has explicitly decided to emulate that lesser majorVersion interface. Every time a new version of XGL and the XGL DDK are released, this DDK document will specify which, if any, DDK major versions are emulated by the device-independent XGL library.

    This release of the DDK (major version 4, minor version 1) is compatible with the device-independent XGL 4.0 library.

  3. The device-independent XGL library always attempts to dynamically load a device pipeline that has the same DDK majorVersion as itself. If the device pipeline depends on functionality that was added in a particular minorVersion of the DDK, your pipeline must check for the existence of that functionality by checking the device-independent library's DDK version number. A device pipeline can check the device-independent library's DDK version number by calling the global library function xglGetDdkVersion(), as declared in xgli/DdkVersion.h, from within its xgli_create_PipeLib() function.

    A device pipeline can provide its own workaround if the functionality does not exist, or it can fail with an appropriate error message indicating the device-independent library version that is required.

Setting Up the Required Pipeline Interface Classes

To set up the framework for your pipeline, you must create the required functions and classes. You can do this either by deriving the required classes from the XGL DDK header files or by copying and modifying a set of derived classes from one of the sample pipelines provided with the XGL DDK product. The steps that follow provide an overview of this task:
  1. Define the xgli_create_PipeLib() routine.

  2. Define an XglDpLib class for your pipeline and implement the required functions.

  3. Define an XglDpMgr class for your pipeline and implement the required functions.

  4. Define an XglDpDev class for your pipeline and implement the required functions and the appropriate optional functions.

  5. Define two XglDpCtx classes for your pipeline, one for 3D and another for 2D. Each of these classes contains an array of function pointers to pipeline renderers.

These steps are discussed in the following sections. Figure 3-2 provides a quick overview of the pipeline instantiation process. For more information on how the XGL device-independent code instantiates the pipeline objects and loads the pipeline during device creation, and for illustrations showing how these classes are associated at runtime, see the XGL Architecture Guide.

图形

Figure 3-2


Note - This chapter contains a number of source code examples. You can copy or modify these examples as long as the resulting code is used to create a loadable pipeline for XGL.

Defining a Function to Create the Device Pipeline Object

As a first step in writing a device pipeline, you must write a function that creates an instance of the XGL device pipeline object (XglDpLib) corresponding to your device pipeline. This function is named xgli_create_PipeLib(). The function is called by the XGL device-independent code through dlsym() (an interface routine in the Solaris dynamic linking mechanism) after the device pipeline is loaded. This function is declared as follows:
extern "C" XglPipeLib* xgli_create_PipeLib()

The extern "C" declaration is needed to disable the C++ name mangling on the function name. Below is a basic implementation of this function, where XglDpLibSampDp represents the name of the XglPipeLib derived class that the device pipeline creates.

  XglPipeLib* xgli_create_PipeLib()  
  {  
     return new XglDpLibSampDp;  
  }  

You can also implement this function to use the XGLI_PIPELINE_CHECK_VERSION() macro in the DdkVersion.h file. This macro verifies that the pipeline was built on the same major version of the GPI as the current library. It also determines whether the minor version of the pipeline is the same as or less than the minor version of the current XGL library. If the version numbers correspond, the macro creates the device pipeline object for the device pipeline. If a pipeline was built on a version of the GPI that is newer than the current library, an error is returned and the XglDpLib object is not instantiated.

  #include "xgli/DdkVersion.h"  
  
  XglPipeLib* xgli_create_PipeLib()  
  {  
      XGLI_PIPELINE_CHECK_VERSION(XglDpLibSampDp);  
  }  

Defining the Device Pipeline Library Class

Next, you must derive a class from the device pipeline library class hierarchy to create your device pipeline library (XglDpLib) class. An object from this class represents a loaded device pipeline and maps to the .so shared object for that pipeline. For each pipeline that is loaded into the XGL environment, there is an XglDpLib object created by the pipeline function xgli_create_PipeLib(). An XglDpLib object does the following:
  • Provides for the creation, management, and destruction of device pipeline manager objects.
  • Allows more than one device pipeline manager object to share hardware or software resources.
  • Provides a location for data relevant to the pipeline library as a whole.
The base class of the device pipeline library hierarchy is XglPipeLib. The device pipeline library class (XglDpLib) and the software pipeline library class (XglSwpLib) derive from this class. You derive your device pipeline implementation from XglDpLib. See the files PipeLib.h and DpLib.h for the definition of these classes. A minimal definition of a pipeline library class is shown here.

  #include "xgl/xgl.h"  
  #include "xgli/DpLib.h"  
  #include "DpMgrSampDp.h"  
  
  class XglDrawable;  
  
  extern "C" XglPipeLib* xgli_create_PipeLib();  
  
  class XglDpLibSampDp : public XglDpLib {  
      friend XglPipeLib* xgli_create_PipeLib();  
  private:  
      XglDpLibSampDp()  { dpMgr = NULL; }  
      ~XglDpLibSampDp();  
  
    // Device-pipelines Dependent Functions -  
    // Redefine in Device Pipelines  
       virtual XglDpMgr* getDpMgr(Xgl_obj_type,  
                                      XglDrawable* drawable=NULL);  
  
       XglDpMgrSampDp* dpMgr;// there is only one dpMgr  
  };  

Multiple Frame Buffers and XglDpLib

If there are two frame buffers on a system but both are of the same type, such as GX, there is one XglDpLib object. If the two frame buffers are different types, such as one GX and one IHV-provided frame buffer, there are two XglDpLib objects, one for each device pipeline. The Global State object in the XGL device-independent code keeps a list of XglDpLib objects so that it can destroy them when XGL is closed. For information on the Global State object, see the XGL Architecture Guide.

Note - If the device pipeline needs to establish exclusive control of any device-dependent behavior for client applications, this control is handled by the device pipeline objects because the XGL device-independent code does not handle device-specific control of applications. If the control is needed for all clients of the same type of frame buffer (regardless of the number of frame buffers), then the XglDpLib object should maintain the control. If the control is required for each frame buffer (if there is more than one), then the XglDpMgr object should handle the control.

XglDpLib Virtual Function

The XglDpLib class contains one virtual function that you must override for your pipeline implementation. This function is described in Table 3-1.
Table 3-1
FunctionDescription
getDpMgr(Xgl_obj_type, XglDrawable* drawable)Called by the XGL core device creation routine when it creates a new XglDpMgr object. The drawable parameter enables the device pipeline to distinguish between different physical frame buffers of the same type; however, this pointer is transient and should not be cached. The Xgl_obj_type parameter is currently ignored; in future releases, it may be used to allow a pipeline to create more than one type of Device object.
A sample implementation of getDpMgr() is shown below.

  XglDpMgr*  
  XglDpLibSampDp::getDpMgr(Xgl_obj_type, XglDrawable* drawable)  
  {  
      XglDpMgr*dpMgr;  
  
      dpMgr = dpMgrList.getDpMgr(drawable->getDevFd());  
      if (dpMgr == NULL) {  
           dpMgr = new XglDpMgrGx(drawable);  
  
           if (dpMgr->getCreationOk()) {  
                dpMgrList.addDpMgr(drawable->getDevFd(), dpMgr);  
           } else {  
                delete dpMgr;  
                dpMgr = NULL;  
           }  
       }  
      return dpMgr;  
  }  

This implementation finds an existing XglDpMgr object or creates a new one using the device-independent utility class, XglListOfDpMgr (defined in ListOfDpMgr.h). This class manages a list of XglDpMgr objects created in implementations that handle multiple frame buffers. This class provides two functions: one to retrieve an existing DpMgr matching a file descriptor, and another to create a new DpMgr for the device.
XglDpMgr* XglListOfDpMgr::getDpMgr(int fildes)
void XglListOfDpMgr::addDpMgr(int fildes, XglDpMgr* mgr)

When the pipeline is closed, the pipeline XglDpLib destructor automatically deletes the list of XglDpMgr objects.
The XglDpMgr object typically includes hardware initialization code as part of its constructor. The XglDpLib object can check on the status of the hardware resources during XglDpMgr instantiation using the getCreationOK() method defined in include/xgli/DbgObject.h. The creationOK variable in XglDpMgr is initially set to TRUE. If a hardware resource failure occurs, creationOK should be set to FALSE, and the XglDpMgr should return. Instantiation of your pipeline will then fail.

Multiple Frame Buffers and XglDpMgr

Systems with multiple frame buffers may have frame buffers of either the same type or different types. Depending on the functions performed by an XglDpMgr object, one XglDpMgr can be created for each frame buffer, or one XglDpMgr can be created for all frame buffers of the same type. If the frame buffers are of the same type, the XglDpMgr objects are created by the unique XglDpLib object for that pipeline. If the frame buffers are different types, each XglDpMgr object is created by the XglDpLib object corresponding to the device pipeline for that frame buffer. For example, for one GX and one Cg3 (color frame buffer), there are two XglDpMgr objects: one XglDpMgrGx object and one XglDpMgrCfb object.
For implementations that handle multiple frame buffers, the XglDpLib object may need to keep a list of previously created XglDpMgr objects. In this case, the getDpMgr() function should check the list for an existing XglDpMgr object associated with the Device type and Drawable object and retrieve the XglDpMgr object if it exists.
Since the number of device pipeline manager objects your pipeline needs depends on the capabilities of your hardware, the creation, managment, and destruction of XglDpMgr objects is left to your individual device pipeline implementation. Typically, the device pipeline provides one XglDpMgr object for each frame buffer, but the pipeline can manage XglDpMgr objects in other ways as well. The destruction of the XglDpMgr objects should be handled in the XglDpLib destructor function, which the XGL device-independent code invokes during xgl_close().
For device pipelines that only need one XglDpMgr, such as a memory raster pipeline, the getDpMgr() function returns the same XglDpMgr object every time it is needed.

Defining the Device Pipeline Manager Class

The next step in setting up the pipeline framework is to define the device pipeline manager (XglDpMgr) class. An object from this class does the following:
  • Provides for the creation of the device pipeline device objects. This class allows multiple device pipeline device objects to share the physical resources of a device.
  • Maintains information about the physical hardware device.
See the file DpMgr.h for the definition of this class. Note that although you can initialize your hardware in any of the framework classes, a good place to initialize the hardware is in your XglDpMgr constructor, since this is where the frame buffer is first notified that XGL is going to use it. A minimal definition of a device pipeline manager class is shown here as XglDpMgrSampDp.

  class XglDevice;  
  class XglDpDev;  
  class XglDrawable;  
  
  class XglDpMgrSampDp : public XglDpMgr {  
  public:  
    virtual ~XglDpMgrSampDp();  
  private:  
    //  
    // Device-pipelines Functions - Redefine in Device Pipelines  
    //  
    virtual XglDpDev* createDpDev(XglDevice*,  
                                 Xgl_obj_desc* bkstore_desc = NULL);  
    virtual void inquire(XglDrawable*, Xgl_inquire*);  
  };  

To limit the number of XglDpMgr objects, you can deny the creation of new XglDpMgr objects by returning NULL from XglDpLibYourFb::getDpMgr(). You can also limit the creation of a new XglDpDev object by returning NULL from XglDpMgrSampDp::createDpDev(). Recoverable errors from the XGL device-independent code result in those situations.

XglDpMgr Virtual Functions

The XglDpMgr class contains two virtual functions that you must override for your pipeline. These virtual functions are described in Table 3-2.
Table 3-2
FunctionDescription
XglDpDev*
createDpDev(XglDevice*,
Xgl_obj_desc*)
Invokes the creation of the device-dependent part of the
XGL Device object. The XglDevice argument is cast to a
pointer to the type of Device being created, such as
XglRasterWin or XglRasterMem. The Xgl_obj_desc
argument is a pointer to a structure containing additional
information about the XGL Device object. The XGL device-
independent code uses the information in this structure,
and the device pipeline normally does not need it.
However, when backing store is enabled, this argument
provides information about the parent device that the
backing-store device can use or ignore.
void inquire(XglDrawable*, Xgl_inquire*)Returns information on the acceleration features underlying a window. This function corresponds to the API xgl_inquire() function. The inquire() function uses the XglDrawable* parameter passed to it to fill the contents of the Xgl_inquire structure whose address is passed. The XglDrawable pointer is transient and is destroyed after being used.
A sample implementation of the createDpDev() function creating a window raster device is shown below.

  XglDpDev* XglDpMgrSampDp::createDpDev (XglDevice* device,  
                                               Xgl_obj_desc*)  
  {  
   return new XglDpDevSampDp(this,(XglRasterWin*)device);  
  }  

What You Should Know About inquire() Your pipeline must set the value of the name variable in the inquire() method to the name or symbol for your company and the name of your device. For example, the company symbol for Sun is SUNW and the name for the GX device is cg6. Thus, on a GX device the xgl_inquire() function would
return SUNW:cg6. Set other values appropriately. If a field is not filled in, the default value is used. Therefore, make sure that the inquire() function is accurate before your pipeline is released, since this function helps applications know how to use your hardware. The default values are listed in Table 3-3.
Table 3-3 xgl_inquire()
FieldDefault Value
namenil
dga_flagFALSE
color_typeBoth indexed and RGB color types are set to 0 (false).
depth0
width0
height0
maximum_buffer0
db_buffer_is_copyFALSE
pt_typeAll point types are set to 0. Point types are pt_dim_2d, pt_dim_3d, pt_type_int, pt_type_float and pt_type_double.
hlhsr_modeXGL_HLHSR_NONE
pickingXGL_INQ_NOT_SUPPORTED
double_bufferXGL_INQ_NOT_SUPPORTED
indexed_colorXGL_INQ_NOT_SUPPORTED
true_colorXGL_INQ_NOT_SUPPORTED
depth_cueingXGL_INQ_NOT_SUPPORTED
lightingXGL_INQ_NOT_SUPPORTED
shadingXGL_INQ_NOT_SUPPORTED
hlhsrXGL_INQ_NOT_SUPPORTED
antialiasingXGL_INQ_NOT_SUPPORTED
stereo0
extns0
It is important to note that the application is requesting information about the window rather than the frame buffer when it executes xgl_inquire(). For example, if the device can accelerate more than one color type, such as 8-bit indexed color and 24-bit RGB color, the application may request the best visual from the X server and then use xgl_inquire() to determine whether it was given a 24-bit window or an 8-bit window. The pipeline inquire() function can test the window depth and then return the appropriate information to the application.
For an implementation of the inquire() function, see the sample GX pipeline provided as part of the XGL DDK product. For more information on the inquire() function, see the xgl_inquire() reference page in the XGL Reference Manual.

Note - inquire() might be called before the XglDpDev object is created, but it will only be called after xgl_open().

Defining the Device Pipeline Device Class

Next, you must derive a class from the device pipeline device hierarchy. An object from this hierarchy contains the device-dependent elements of an XGL Device object and is linked to the device-independent part of the Device object. An object instantiated from the XglDpDev class does the following:
  • Creates the device pipeline-context objects
  • Provides a device pipeline with the opportunity to exchange device information with the XGL device-independent code via get() and set() functions
  • Provides a storage location for data relevant to the window
In the case of a single XGL application with multiple windows, each XglDpDev object maps to a single window on the screen. If the application has multiple windows using the same underlying frame buffer, the XglDpMgr object for that frame buffer creates all the XglDpDev objects that the application needs. If the application runs on a system with more than one physical frame buffer, and the application creates multiple windows on each frame buffer, each XglDpDev object is created by the XglDpMgr object that corresponds to the frame buffer.
Although the XglDpMgr object creates multiple XglDpDev objects, it is not designed to keep track of those objects. Instead, for each XGL API-level Device object that is created, a pointer to the XglDpDev object is returned to the device-independent XglRasterWin object, and a pointer to the XglRasterWin object is stored in the XglSysState object list of existing Device objects. For more information on how pipeline objects are instantiated, see the XGL Architecture Guide.
The base class of the device-dependent device hierarchy is XglDpDev. The XglDpDevRaster derives from this class, and the XglDpDevWinRas, XglDpDevMemRas, and XglDpDevStream derive from XglDpDevRaster. Depending on the type of the device you are porting, your device pipeline will derive a device class from either XglDpDevWinRas (for window rasters), XglDpDevMemRas (for memory rasters), or XglDpDevStream (for stream devices). See the header files DpDev.h, DpDevRaster.h, DpDevWinRas.h, DpDevMemRas.h., and DpDevStream.h for the device-dependent hierarchy. Sample code for a minimal definition of a device-pipeline device class for a window raster is shown below.

  class XglDpDevSampDp : public XglDpDevWinRas {  
           friend XglDpMgrSampDp;  
  private:  
     XglDpDevSampDp(XglDevice* device) : XglDpDevWinRas(device) {}  
        //  
        // Device-pipelines Dependent Functions -  
        // Redefine in Device Pipelines  
        //  
     virtual XglDpCtx3d* createDpCtx(XglContext3d*);  
     virtual XglDpCtx2d* createDpCtx(XglContext2d*);  
  
     virtual int copyBuffer(  
        XglContext3d*,    //3D Context associated with dst mem_ras  
        Xgl_bounds_i2d*,  //Rectangle  
        Xgl_pt_i2d*);     //Position  
  
     virtual int copyBuffer(  
        XglContext2d*,    //2D Context associated with dst mem_ras  
        Xgl_bounds_i2d*,  //Rectangle  
        Xgl_pt_i2d*);     //Position  
  };  


Note - When XglDpDevWinRas is created, a device pipeline should call XglRasterWin:setDgaCmapPutFunc() to register the callback function that updates the hardware color map. For information on setDgaCmapPutFunc(), see "Window Raster Interfaces" on page 109.

XglDpDev Virtual Functions

A minimal implementation of the XglDpDev class contains several functions that the pipeline must override. These functions are described in Table 3-4.
Table 3-4
FunctionDescription
virtual XglDpCtx{2/3}d*
createDpCtx(XglContext{2/3}d*)
Creates the XglDpCtx objects. Two of these functions must
be created, one for 2D and one for 3D.
virtual int

copyBuffer(XglContext{2/3}d*, Xgl_bounds_i2d*, Xgl_pt_i2d*)

Copies from one buffer to another. The destination device is the memory raster associated with the Context parameter, and the source device is the pipeline XglDpDev object. Two of these functions must be created, one for 2D and one for 3D.
The XglDpDev class and its hierarchy include a number of virtual functions that the pipeline can override to perform operations specific to the device. The functions relevant to a window raster device are listed in Table 3-5 on page 42.
XGL has defined default behavior for these functions. If the default behavior of your hardware matches the defaults that XGL has defined for these functions, it is not necessary to override these functions.
Table 3-5
ClassFunction DeclarationDefault Action or Value
XglDpDevXgl_vdc_orientation getDcOrientation() float getMaxZ()

float getGammaValue()

XGL_Y_DOWN_Z_AWAY XGLI_DEFAULT_MAX_DEPTH 2.22
XglDpDevRastervoid setRectList(const Xgl_irect[])
void setRectNum(Xgl_usgn32)
void setSourceBuffer(Xgl_buffer_sel)
void setSwZBuffer(XglPixRectMem*)
void setSwAccumBuffer(XglPixRectMem*)
void syncRtnDevice(XglRasterWin*)
No operation
No operation
No operation
No operation
No operation
No operation
XglDpDevWinRasXgl_accum_depth getAccumBufferDepth()
Xgl_usgn32 getDepth()
Xgl_color_type getRealColorType()
XglPixRectMem* getSwZBuffer()
XglPixRectMem* getSwAccumBuffer()
Xgl_boolean needRtnDevice()
void resize()
void setBackingStore(Xgl_boolean)
void setBufDisplay(Xgl_usgn32)
void setBufDraw(Xgl_usgn32)
void setBufMinDelay(Xgl_usgn32)
Xgl_usgn32 setBuffersRequested(Xgl_usgn32)
void setCmap(XglCmap*)
void setPixelMapping(const Xgl_usgn32)
void setStereoMode(Xgl_stereo_mode)
XGL_ACCUM_DEPTH_2X
Query Drawable for win depth
Query Drawable for fb color type
NULL
NULL
TRUE
No operation
No operation
No operation
No operation
No operation
Returns one buffer
No operation
No operation
No operation

Device Object Initialization

It is important to be aware that XGL's API-level Device object consists of two internal objects: the device-dependent device object created by the device pipeline XglDpMgr object, and a device-independent object, such as XglRasterWin, created by the System State object. These two internal Device objects are linked by a pointer from the device-dependent object to the device-independent object. The API Device object was designed with separate device-independent and device-dependent components to isolate the device-dependent operations. This design allows you to define specific operations for your device.
When the XGL device-independent code asks the device pipeline to create an XglDpDev object, it passes a handle to the device-independent Device object:
XglDpDev* XglDpMgrYourFb::createDpDev(XglDevice* device)

At creation time, the XglDpDev object gets from the XglDevice object all the information it needs about the device-independent attributes. The device-independent values are valid at this time. Most of the set...() functions are called later when the application changes device-dependent parameters through the API.
After getting the pointer to the XglDpDev object, the XglRasterWin object calls the device-dependent object's get...() functions to complete its own initialization. You should not expect these device-dependent attributes, which provide information such as the DC orientation or the device color type, to be meaningful during the XglDpDev object creation. Later in the process of pipeline initialization, XglRasterWin calls set...() functions that allow the XglDpDev object to complete its initialization with the correct device-dependent data.

Defining the Device Pipeline-Context Class

The final step in creating your pipeline derived classes is to derive a class from the device pipeline-context hierarchy. If your pipeline supports applications that render in 2D and 3D, then two classes are needed, one descending from XglDpCtx2d and the other from XglDpCtx3d.
The two XglDpCtx classes contain the interfaces for the 2D and 3D LI-1, LI-2, and LI-3 primitive layers. The LI-1 and LI-2 interfaces are methods that you can override in your device pipeline if the hardware supports the primitives. By default, the device pipeline-context object calls the software pipeline to perform LI-1 and LI-2 operations. The LI-3 functions must be implemented by the device pipeline since these functions are device dependent. There is one device pipeline-context object per Device-Context pair.
An XglDpCtx class for a 3D pipeline in which only multipolylines are implemented might look like the following sample code.

  class XglDpCtx3dSampDp : public XglDpCtx3d {  
      friend XglDpDevSampDp;  
  private:  
      XglDpCtx3dSampDp(XglContext3d* context) :  
      XglDpCtx3d(context) {  
           opsVec[XGLI_LI1_MULTIPOLYLINE] =  
            XGLI_OPS(XglDpCtx3dSampDp::li1MultiPolyline);  
           opsVec[XGLI_LI_OBJ_SET] =  
            XGLI_OPS(XglDpCtx3dSampDp::objectSet);  
           opsVec[XGLI_LI_MXG_RCV] =  
            XGLI_OPS(XglDpCtx3dSampDp::messageReceive);  
       }  
      //  
      // Device-pipeline Dependent Functions  
      //  
      void li1MultiPolyline(Xgl_bbox*, Xgl_usgn32, Xgl_pt_list*);  
  
      // Function to handle ctx related changes  
      void  objectSet (const  Xgl_attribute*);  
  
       //Function to draw the line through the hardware  
       void drawLine (Xgl_usgn32, Xgl_pt_list*);  
  };  

The LI functions are described in Chapter 8, Chapter 9, and Chapter 10. For information on switching between the device pipeline and the software pipeline, see "Calling the Software Pipeline" on page 50.

Rendering Through the XglDpCtx Object

When a primitive is called, the XGL device-independent code maps the API call to an internal C++ call in a wrapper function. The wrapper passes the primitive call directly to the device pipeline through the opsVec[] array. The opsVec[] is a dynamic array of function pointers to LI functions. It is defined by the XGL device-independent code and maintained by the device pipeline. The array is defined as shown below. XGLI_OPS is defined in DpCtx.h as (void(XglDpCtx::*)()).

  XglDpCtx3d::XglDpCtx3d(XglDevice*    dev,  
                         XglContext3d* context) : XglPipeCtx3d(context)  
  {  
      //  
      // Initialize DI opsVec[]  
      //  
      opsVec[XGLI_LI1_NEW_FRAME] =  
                XGLI_OPS(XglDpCtx3d::li1NewFrame);  
      opsVec[XGLI_LI1_GET_PIXEL] =  
                XGLI_OPS(XglDpCtx3d::li1GetPixel);  
      opsVec[XGLI_LI1_SET_PIXEL] =  
                XGLI_OPS(XglDpCtx3d::li1SetPixel);  
      opsVec[XGLI_LI1_SET_MULTI_PIXEL] =  
                XGLI_OPS(XglDpCtx3d::li1SetMultiPixel);  
      opsVec[XGLI_LI1_SET_PIXEL_ROW] =  
                XGLI_OPS(XglDpCtx3d::li1SetPixelRow);  
      opsVec[XGLI_LI1_COPY_BUFFER] =  
                XGLI_OPS(XglDpCtx3d::li1CopyBuffer);  
      opsVec[XGLI_LI1_ACCUMULATE] =  
                XGLI_OPS(XglDpCtx3d::li1Accumulate);  
      opsVec[XGLI_LI1_CLEAR_ACCUMULATION] =  
                XGLI_OPS(XglDpCtx3d::li1ClearAccumulation);  
      :  
      :  
      :  
  }  

When the application calls a primitive, the wrapper forwards the API function call to the device pipeline, as shown in the following sample wrapper function.

  void xgl_multipolyline(Xgl_ctx      ctx,  
                         Xgl_bbox*    bounding_box,  
                         Xgl_usgn32   num_pt_lists,  
                         Xgl_pt_list* pl)  
  {  
      XglDpCtx* dp = ((XglCtxObject*)ctx)->getDp(); //get dp pointer  
           (dp->*( //call dp function pointed to by mpline array entry  
             (void(XglDpCtx::*)(Xgl_bbox*,Xgl_usgn32,Xgl_pt_list*))  
             (dp->currOpsVec[XGLI_LI1_MULTIPOLYLINE])  
            )  
      )(bounding_box,num_pt_lists,pl); // function called with API  
                                       // args  
  }  


Note - At LI-1, API geometry data is passed to the device pipeline unchanged.

Required Initialization of the opsVec[] Function Array

The XGL device-independent code initializes the opsVec[] array to a set of default function pointers that point to the software pipeline LI-1 primitives. It is the device pipeline's responsibility to override the entries in the opsVec[] array with functions that the device pipeline has implemented. This can occur at initialization of the pipeline XglDpCtx object (when the Device is set on the Context) or during program execution. In deciding how to set up your pipeline's opsVec[] array, you have three cases to consider:
  • Primitives that the pipeline does not implement. The XGL software pipeline is used for LI-1 and LI-2 operations for these primitives.
  • Primitives that the pipeline implements but that are not critical to performance.
  • Primitives that the pipeline implements but that are critical to performance.
Designing the opsVec[] array to handle these cases is discussed below.
Using the Default Software Pipeline Renderer The opsVec[] array entries are loaded with calls to the LI-1 and LI-2 software pipeline by default. If your device pipeline has not implemented a particular LI-1 or LI-2 primitive, you do not need to change the opsVec[] array. Your XglDpCtx object will inherit the default software pipeline calls. The XglDpCtx3d default call to the software pipeline looks like this:

  void XglDpCtx3d::li1MultiPolyline(Xgl_bbox*    bounding_box,  
                                    Xgl_usgn32   num_pt_lists,  
                                    Xgl_pt_list* pl)  
  {  
      if (error_checking) {  
          do_error_checking()  
      }  
      swp->li1MultiPolyline(bounding_box, num_pt_lists, pl);  
  }  

Implementing a Generic Renderer If your pipeline implements a primitive, but the primitive's performance is not critical, the pipeline can load a pointer to its primitive function when the Device is set on the Context and not reset it later. This function will be called whenever the application calls a primitive.
To provide a renderer, declare the function as a member of your pipeline XglDpCtx. In the XglDpCtx's constructor, put a pointer to the function in the appropriate entry of the opsVec[] array. A list of opsVec[] array indices can be found in DpCtx.h.
An example of initializing the opsVec[] array for a device pipeline LI-1 multipolyline function is shown below.

  //  
  // Install multipolyline  
  //  
  opsVec[XGLI_LI1_MULTIPOLYLINE] =  
          XGLI_OPS(XglDpCtx3dSampleDp::li1MultiPolyline);  

Implementing a Performance-Critical Renderer If your device pipeline implements a primitive whose performance is critical, you may want to create a set of renderers for this primitive. The set might include:
  • A single generic renderer that does error checking and handles point type changes, attribute changes, and transform changes.
  • One or more fast renderers that do not need to handle point type changes or other changes, and that are tuned to specific combinations of attributes.
A generic renderer might look something like this:

  //  
  // Get and return clip-changed status.  
  //  
  // Result OR'ed and saved in "clipChanged" since  
  // drawable->clipChanged() does not retain clip status.  
  //  
  #define GX_CLIP_CHANGED(drawable) (clipChanged |=  \  
                         (drawable)->clipChanged())  
  XglDpCtx3dGx::GenericMpline(Xgl_bbox*    bounding_box,  
                              Xgl_usgn32   num_pt_lists,  


                              Xgl_pt_list* pl)  
  {  
      if (error_checking) {  
          do_error_checking()  
      }  
      if (ctx != last_ctx) {  
          // handle context change  
      }  
      if (pt_type != last_pt_type) {  
          // handle point type change  
      }  
      if (prim != last_prim)  {  
          // handle primitive type change  
      }  
      if (GX_CLIP_CHANGED(drawable)) {  
          // handle window type change  
      }  
      if (xforms_changed) {  
          // handle transform changes  
      }  
      // Figure out which fast line renderer to use and set  
      // opsVec[XGLI_LI1_MULTIPOLYLINE] to this line renderer.  
  
      // window locking  
      // model clipping  
  
       // Draw the multipolyline with the fast renderer you just set.  
      (this->*((void(XglDpCtx3dGx::*)  
                (Xgl_bbox*, Xgl_usgn32, Xgl_pt_list*, Xgl_boolean)  
               )(opsVec[XGLI_LI1_MULTIPOLYLINE])  
              )  
      )(bounding_box, num_pt_lists, pl, FALSE);  
  
     // If nothing changes, this fast renderer will be  
     // called directly the next time.  
  
     // window unlocking  
  }  


Note - The optional parameter Xgl_boolean in the rendering call controls which code renders to backing store. If this parameter is set to FALSE, the software pipeline will render to backing store; otherwise, the device-independent code will render to backing store. If the device pipeline is handling backing store, once the primitive is rendered to backing store, then set the parameter drawBackingStore = FALSE. For an example of the use of drawBackingStore, the the XGL Architecture Guide.

A fast renderer might look something like this:

  XglDpCtx3dGx::FastMPline()  
  {  
     //state changes that require re-evaluation before renderering  
     if (ctx!=last_ctx || pt_type!=last_pt_type ||  
         prim!=last_prim || DP_CLIP_CHANGED(drawable)) {  
           GenericMpline();  
     }     return;  
     // send the points to the hardware to render  
  }  

A device pipeline rendering function can override opsVec[] entries at any time. You can design a renderer to support a particular set of attributes and install that renderer during program execution. This frees some renderers from having to test the attributes in each primitive call, and thus provides improved acceleration.
If a device decides to set an opsVec[] entry back to its default value, the opsVecDiDefault[] array can be used:

  // Set opsVec[] back to default  
  opsVec[XGLI_LI1_MULTIPOLYLINE] =  
          opsVecDiDefault[XGLI_LI1_MULTIPOLYLINE];  

Calling the Software Pipeline

If a device pipeline cannot accelerate the API arguments or the Context state (for example, API attributes, point type, or facet flags), the pipeline can call the software pipeline directly, as shown in this example.

  void XglDpCtx3dSampDp::li1MultiPolyline(  
     Xgl_bbox*     bounding_box,  
     Xgl_usgn32    num_pt_lists,  
     Xgl_pt_list*  pl)  
  
  {  
      const XglStrokeGroup3d* cur_stroke = ctx->getCurrentStroke();  
  
      // Check if dp can render with the current attrs  
      // e.g. If dp can handle only line style solid then  
      // dp must call software pipeline  
      if ( cur_stroke->getStyle() != XGL_LINE_SOLID) {  
          swp->li1MultiPolyline(bounding_box, num_pt_lists, pl);  
      }   return;  
  
      // Draw the polyline  
       drawLine(num_pt_lists, pl);  
  }  

When a device pipeline can only render part of a primitive, it can fall back to the software pipeline for partial rendering of the primitive. For example, to handle a complex polygon in an xgl_multi_simple_polygon() call, the device pipeline can do the following.

  // Second version of a fast renderer.  
  // Get and return clip changed status.  
  //  
  // Result OR'ed and saved in "clipChanged" since  
  // drawable->clipChanged() does not retain clip status.  
  //  
  #define GX_CLIP_CHANGED(drawable) (clipChanged |=  \  
                         (drawable)->clipChanged())  
  
  XglDpCtx3dGx::li1FastMsp(Xgl_facet_flags api_facet_flags,  
                           Xgl_facet_list  *api_facet_list,  
                           Xgl_bbox        *api_bbox,  
                           Xgl_usgn32      api_num_pt_lists,  
                           Xgl_pt_list     *api_pt_list)  


  {  
      // API arguments that can't be handled by the dp.  
      if (api_pt_list->pt_type & XGL__HOM) { // Homogeneous point  
                                             // type  
          swp->li1MultiSimplePolygon(api_facet_flags,  
                                     api_facet_list,  
                                     api_bbox, api_num_pt_lists,  
                                     api_pt_list);  
          return;  
      }  
  
      // State changes that require re-evaluation before  
      // rendering.  
      if (ctx != dp_saved_last_ctx_ptr ||  
         api_pt_list->pt_type != dp_saved_last_pt_type ||  
         api_facet_flags != dp_saved_last_facet_flags ||  
         api_facet_list->facet_type != dp_saved_last_facet_type ||  
         dp_saved_prim != dp_saved_last_prim ||  
         GX_CLIP_CHANGED(drawable)) {  
  
         li1MultiSimplePolygon(api_facet_flags, api_facet_list,  
                               api_bbox,api_num_pt_lists, api_pt_list);  
         return;  
      }  
      Xgl_pt_list *pl = api_pt_list;  
      for(Xgl_usgn32 i = 0; i < api_num_pt_lists; pl++) { // for  
                                                           each polygon  
          if (api_facet_flags & XGL_FACET_FLAG_SHAPE_CONVEX)  
              //  
              // if convex  
               // send the points to the hardware  
              //  
          else  
              //  
              // Parts of the primitive that can't be handled  
              //  
           swp->li1Polygon(api_facet_list->facet_type,  
                          api_facet_list->facets,  
                           api_bbox,  
                           1,  
                          pl);  
      }  
  }  

What Else You Should Know

This section provides additional information about the pipeline interface classes that you might need to know as you set up your device pipeline.

How a Device Pipeline Is Loaded

A device pipeline is loaded when the application calls xgl_inquire() or calls xgl_object_create() to create a Device object for the first time. With the device object creation call, the application passes in the device type and the descriptor containing the X window identifying information. The XGL device-independent code then proceeds to create the objects needed for the pipeline. The pipeline loading part of this process is as follows:
  1. When the application requests a Device object with xgl_object_create(), the System State object initiates the creation of the device-independent part of the Device object. In the case of a window raster, XglRasterWin is created.

  2. XglRasterWin calls XglDrawable::grabDrawable() to obtain an XglDrawable object of the appropriate type for the XGL device.

  3. During the creation process of XglRasterWin, the Device object asks the XglGlobalState object to create its device-dependent part.

  4. In the process of creating the device-dependent part of the Device object, the XglGlobalState object does the following:

    a. It gets the name of the pipeline shared object file by calling the Window Raster's XglDrawable::getPipeName() routine. This routine issues a system call to the kernel device driver, using the VIS_GETIDENTIFIER ioctl(), to get a string specifying the name of the device when the device is a frame buffer. This string can then be used to create the pipeline name, which is of the form:

    xgl<COMPANY NAME><device name>.so.<major version>

    For information on the VIS_GETIDENTIFIER ioctl(), see visual_io(7) in the Solaris Reference Manual.

    b. The XglGlobalState::getDpLib() routine then traverses the Global State's XglDpLibList object list to determine if an object for the pipeline library already exists. If so, it returns.

If XglGlobalState does not find a match in its XglDpLibList, XglGlobalState::loadPipeLib() loads the pipeline using dlopen(), which is an interface routine in the Solaris dynamic linking mechanism. dlopen() gives XGL runtime access to the device pipeline shared object file and binds it to XGL's process address space.
c. XglGlobalState::loadPipeLib() then creates the XglDpLib object for the pipeline by calling the device pipeline's xgli_create_PipeLib() routine, which is defined in the pipeline and accessed through dlsym(). This routine first checks the DDK major and minor version numbers to ensure that the pipeline is compatible with the XGL library that is attempting to load it. If this check succeeds, xgli_create_PipeLib() creates an instance of the pipeline-derived XglDpLib class and returns a pointer to the object. This pointer is appended to the XglGlobalState's XglDpLibList object for future reference. The XglDpLib object represents a single pipeline.
At this point, the process of pipeline object creation continues with the instantiation of the pipeline XglDpMgr object and the pipeline XglDpDev object. For detailed information on the complete set of steps that occur during pipeline creation, see the XGL Architecture Guide.

Supporting DGA Transparent Overlay Windows

The XGL library supports the use of transparent overlay windows. Transparent overlay windows allow applications to render simple temporary items such as menus on complex rendering in the underlying window. The transparent overlay functionality in XGL requires that the server provide overlay support, as the Solaris overlay extension in the Solaris server does.
If the user asks for transparent overlay functionality and the application determines that the server provides overlay support, the application may request an XGL window raster for transparent overlay rendering. XGL can provide this support through the Xpex pipeline, or if the hardware device includes hardware overlay planes and the device pipeline implements overlay support, the device pipeline can provide this support.
When the application requests an XGL window raster, XGL will determine whether DGA support for overlays is available, and if not, XGL will open the Xpex pipeline. Even if DGA support of overlays is available, there may be some cases in which DGA will refuse to grant the request for the overlay Drawable, and in these cases XGL will use the Xpex pipeline for transparent
overlay rendering. For example, the server will always deny access to an overlay Drawable on a window with backing store. If the Solaris server allows XGL to grab an overlay Drawable, XGL will attempt to open the device pipeline for the window. At some point during device pipeline initialization, the pipeline should determine whether the Drawable for the window is an overlay Drawable. To do this, use the XglDrawable interface getDrawType(), as in the following example:
isOvl = (drawable->getDrawType() == DGA_DRAW_OVERLAY);

If the hardware does not have hardware overlay planes, the pipeline can abort pipeline initialization, and XGL will not support transparent overlays through this pipeline. Even if the hardware has hardware overlay planes, the device pipeline may choose not to support transparent overlay windows through DGA and let XGL fall back to the Xpex pipeline for transparent overlay windows. To abort pipeline initialization, use the getCreationOK() function defined in DbgObject.h.

Note - If the device pipeline opens as an overlay window, the pipeline is then responsible for all rendering, as the use of the software pipeline for overlay rendering is undefined.

Device Pipeline Objects for Multiple Processes

When a pipeline is instantiated on a single frame buffer from a single application, the device pipeline objects in Figure 3-3 are created.

图形

Figure 3-3

When a single application opens windows on a two-headed system in which the frame buffers are the same type, there is one XglDpLib object, an XglDpMgr for each frame buffer, and an XglDpDev object for each window. The single application program is one UNIX process. A diagram of a single application opening one window on each of two identical frame buffers would look like Figure 3-4.

图形

Figure 3-4

When there is more than one application program using XGL, there is a UNIX process for each application. If there are two application programs, there are two UNIX processes. In this case, there is an XglDpLib object for each process, an XglDpMgr object corresponding to each XglDpLib, and an XglDpDev object for each window. Figure 3-5 shows the pipeline objects that are created for two application programs running on one frame buffer. The second application opens two windows.

图形

Figure 3-5

The XGL/DGA system does not describe how an accelerator accommodates two or more application processes. DGA is basically a concurrency control mechanism; it serializes concurrent accesses, but it does not mandate how the accelerator handles state information for different processes. You must coordinate the interaction between the XglDpLib objects for each process.
If the application programs run on a two-headed system with frame buffers of different types, your frame buffer and a GX frame buffer for example, the pipeline objects might look like Figure 3-6.

图形

Figure 3-6

Adding Member Data to a Pipeline Class

When creating pipeline classes, you can add member data whenever needed. The following example illustrates a way to add and initialize a pointer to the device manager as member data in the XglDpDev and XglDpCtx classes.
  1. First, add a device pipeline manager pointer as member data and a device pipeline manager parameter to the constructors of XglDpDevSampDp and XglDpCtx[2/3]dSampDp.


  class XglDpDevSampDp : public XglDpDevWinRas {  
      friend XglDpLibSampDp;  
  private:  
      // call base class constructor with device, assign device  
      // manager pointer (dev_mgr) to member data dpMgr  
      XglDpDevSampDp(XglDevice* device, XglDpMgrSampDp* dev_mgr)  
                  : XglDpDevWinRas(device), dpMgr(dev_mgr) { }  
  
      XglDpMgrSampDp* dpMgr;   // device manager pointer  
      //        .... other declarations  
  };  
  
  class XglDpCtx3dSampDp : public XglDpCtx3d {  
      friend XglDpDevSampDp;  
  private:  
      // call base class constructor with context, assign device  
      // manager pointer (dev_mgr) to member data dpMgr  
    XglDpCtx3dSampDp(XglContext3d* context, XglDpMgrSampDp*  
  dev_mgr  


      : XglDpCtx3d(context), dpMgr(dev_mgr)  
     {  
         opsVec[XGLI_LI1_MULTIPOLYLINE] =  
             XGLI_OPS(XglDpCtx3dSampDp::li1MultiPolyline);  
           // ....  other declaractions  
     }  
      XglDpMgrSampDp* dpMgr;        // device manager pointer  
      //  .... other declarations  
  };  

  1. Modify the object-creation functions to pass the device manager pointer to the constructors.


  XglDpDev* XglDpMgrSampDp::createDpDev(XglDevice* device)  
  {  
      // "this" is the device manager (XglDpMgrSampDp) itself  
      return new XglDpDevSampDp(device,this);  
  }  
  
  XglDpCtx3d* XglDpDevSampDp::createDpCtx(XglContext3d* context)  
  {  
      // here dpMgr is a member data of XglDpDevSampDp  
      return new XglDpCtx3dSampDp(context,dpMgr);  
  }  

Backing-Store Support in the Pipeline Classes

The XGL device-independent code is responsible for handling XGL backing-store device creation and use. The device pipeline needs only to implement a small set of device-dependent functions in certain cases. This section summarizes the functions that the device pipeline needs to implement. For more information on how the XGL device-independent code handles backing store, see the XGL Architecture Guide.

Backing Store Clipping Status Values

If the device pipeline can determine whether a primitive is clipped, it can notify the device-independent layer with the setPrimClipStatus() function to indicate the current status. The following argument values are defined in DpCtx.h:
XGLI_DP_STATUS_FAIL                         The primitive was  not  rendered.

XGLI_DP_STATUS_SUCCESS                      The primitive was successfully 
                                            rendered and may or may not have 
                                            been clipped.

XGLI_DP_STATUS_FULLY_RENDERED               The primitive was successfully 
                                            rendered without being clipped.

You can use the value XGLI_DP_STATUS_FULLY_RENDERED for all the primitives at the LI-1 level. This value means that the primitive was successfully rendered, and that the primitive was fully rendered into the window without any clipping. This argument value is optional and applies only to synchronous accelerators (those without queues). If the graphics device cannot determine whether the primitive is clipped, it is not necessary to call setPrimClipStatus().
The XGLI_DP_STATUS_FULLY_RENDERED value is an optimization to improve the performance of applications using backing store when the window is partially covered. If a device pipeline can set this status, performance is increased if there is a backing-store device and if the window is partially covered. This optimization does not apply to accelerators that cannot determine the clip status.

Note - The device pipeline should never set the value XGLI_DP_STATUS_UNCLIPPED (defined in DpCtx.h). This value is for internal use only.

Backing Store in Window Raster Pipelines

The following functions in XglDpDevWinRas.h should be overridden by all devices that provide Z-buffers or accumulation buffers in software. For information on these functions, see "Virtual Functions in DpDevWinRas.h" on page 62.
  • virtual XglPixRectMem* getSwZBuffer()
  • virtual XglPixRectMem* getSwAccumBuffer()
Device pipelines that can handle backing store in hardware or the X11 server (for example, the PEXlib pipeline) override the following function. A pipeline that returns FALSE can ignore the remainder of the functions in this section.
  • virtual Xgl_boolean needRtnDevice()

Backing-Store Support for Backing Store Devices

Devices that provide backing-store support, such as memory raster devices or a hardware device with a cache for backing-store memory, override these functions declared in XglDpDevRaster.h. For information, see "Virtual Functions in DpDevRaster.h" on page 61.
  • virtual void setSwZBuffer(XglPixRectMem*)
  • virtual void setSwAccumBuffer(XglPixRectMem*)
  • virtual void syncRtnDevice(XglRasterWin*)

Backing-Store Support in the Dp Manager

The device pipeline manager object provides an object descriptor for the backing store device:
XglDpDev* XglDpMgrFb::createDpDev(XglDevice*,
                                     Xgl_obj_desc* bkstore_desc=NULL);

When the XGL device-independent code creates a backing store device, it passes in the descriptor as follows:
bkstore_desc.win_ras.type = XGL_WIN_RAS_BACKING_STORE;
bkstore_desc.win_ras.desc = (pointer to the parent device);

A device pipeline can ignore this parameter if appropriate.

Note - The XGL API cannot support backing store and double buffering at the same time. Even if your device can support both, there are issues regarding the synchronization of double buffering and backing store with the X11 server that are not resolved in the current release of the server. Therefore, an application backing store request is denied by the XGL device-independent code when double buffering is enabled. Thus, even if your pipeline supports both double buffering and backing store, the pipeline will not be called for backing store when double buffering is enabled. See the XGL_WIN_RAS_BACKING_STORE reference page for more information.

Description of Device-Dependent Virtual Functions

This section provides a brief description of the optional device-dependent functions provided in the XglDpDev class hierarchy. Many of these functions have a corresponding API attribute; in these cases, the attribute name is included in the description, and you can find more information about the attribute in the XGL Reference Manual.

Virtual Functions in DpDev.h

virtual Xgl_vdc_orientation getDcOrientation()
  Returns a value for the orientation of DC for the hardware device. The
  default value is XGL_Y_DOWN_Z_AWAY. Override this function if your device
  has a different orientation. This function is called by the XGL device-
  independent code as part of the Device object initialization.

virtual float getMaxZ() Returns a value for the hardware device's maximum Z coordinate value. The default value is XGLI_DEFAULT_MAX_DEPTH, which is a constant defined as 224-1. Override this function if your device has a different maximum Z value. This function is called by the XGL device-independent code as part of the Device object initialization.

Note - If you use the software pipeline or RefDpCtx for rendering, then the device maximum Z value should not exceed 24 bits. Otherwise, the maximum Z value can be set to any value.

virtual float getGammaValue() The default implementation of this function returns a value of 2.22. The function also checks the environment variable XGL_AA_GAMMA_VALUE and returns the value that the environment variable is set to, if it is set. For information on this environment variable, see Appendix B, "Software Rendering Characteristics" in the XGL Programmer's Guide.
The value returned by this function is used as the gamma value to build gamma and inverse gamma look-up tables. These tables are built by buildGammaTables(), which is called by the constructors for objects like XglRasterWin and XglRasterMem. The gamma and inverse gamma tables are only used for manipulating the colors of antialiased stroke and dot primitives. If a device implements antialiasing in hardware, then these
tables, and hence the getGammaValue() function have no effect. However, if the device expects stroke or dot antialiasing to be done by the software pipeline, there are two possible cases. First, if the device does its own gamma correction, the function needs to return the value 1.0. Otherwise, the device can choose to not implement this function or to implement it to return a gamma value that is more suitable.

Note - This function might not be present in future releases of XGL; check the current header files for the most up-to-date list of optional functions.

Virtual Functions in DpDevRaster.h

virtual void setRectList(const Xgl_irect[]) Sets the list of clip rectangles in the application-specified clip list. The input argument is an Xgl_irect array of rectangles that defines the clip region. This function maps to the API attribute XGL_RAS_RECT_LIST and is used by the XGL device-independent code to inform the pipeline when the clip list changes. The default is no operation. For information on this environment variable, see the XGL_RAS_RECT_LIST reference page.
virtual void setRectNum(Xgl_usgn32) Sets the number of clip rectangles in the application-specified clip list. The input argument is an unsigned 32-bit integer. This function maps to the API attribute XGL_RAS_RECT_NUM and is used by the XGL device-independent code to inform the pipeline when the clip list changes. The default is no operation. For more information, see the XGL_RAS_RECT_NUM reference page.
virtual void setSourceBuffer(Xgl_buffer_sel) Specifies the buffer used as the source buffer during raster operations. The input argument is a macro value from the Xgl_buffer_sel typedef. This function maps to the API attribute XGL_RAS_SOURCE_BUFFER and is used by the XGL device-independent code to inform the pipeline when the source buffer for raster operations changes. The default is no operation. For more information, see the XGL_RAS_SOURCE_BUFFER reference page.
virtual void setSwZBuffer(XglPixRectMem*) Specifies that if the device uses a software Z-buffer, it should share it with the base device in the backing store device by getting the memory address and linebytes from the Z-buffer and reassigning them as its own. This
function is called by the XGL device-independent code when the device is a backing store device, so the device pipelines do not need to check for it. The default is no operation.
virtual void setSwAccumBuffer(XglPixRectMem*) Specifies that if the device uses a software accumulation buffer, it should share the same software accumulation buffer with the base device in the backing store device by getting the memory address and linebytes from the accumulation buffer and reassigning them as its own. The XGL device-independent code calls this function when the device is a backing store device, so the device pipelines do not need to check for it. The default is no operation.
virtual void syncRtnDevice(XglRasterWin*) Synchronizes any device-dependent attributes, if needed, for backing store devices. The default is no operation.

Virtual Functions in DpDevWinRas.h

virtual Xgl_usgn32 getDepth()
  Returns the number of bits required to store the color of one pixel in the
  image buffer of this hardware device. The default behavior is to query the
  Drawable object for the depth of the frame buffer image buffer.

virtual Xgl_accum_depth getAccumBufferDepth() Returns the accumulation buffer depth supported by the device. Called by the XGL device-independent code during the creation of the XglDpDev object. This function is currently only used by the software pipeline when doing accumulation. The default return value is XGL_ACCUM_DEPTH_2X, which indicates that the depth of the accumulation buffer is at least twice the depth of the raster.
virtual Xgl_color_type getRealColorType()
  Returns the real color type of the device. The default behavior is to query
  the Drawable object for the real color type of the frame buffer.

virtual void resize() Called by the XGL device-independent code when the pipeline's window is resized. The default is no operation.
virtual void setBackingStore(Xgl_boolean) Requests backing-store support from the device. No device pipeline operation is needed if the device relies on the XGL device-independent code to handle backing store manipulation. The input argument is a Boolean that indicates the on/off setting for backing store. The default is no operation. This function maps to the API attribute XGL_WIN_RAS_BACKING_STORE; see the XGL_WIN_RAS_BACKING_STORE reference page for more information.
virtual Xgl_usgn32 setBuffersRequested(Xgl_usgn32)
  Defines the number of buffers requested by the application. This function
  maps to the API attribute XGL_WIN_RAS_BUFFERS_REQUESTED and is used
  by the XGL device-independent code to request single or double buffering
  for the device. The default return value is one buffer.

virtual void setBufDraw(Xgl_usgn32)
  Specifies the current draw buffer. This function maps to the API attribute
  XGL_WIN_RAS_BUF_DRAW and is used by the XGL device-independent code
  to set the current draw buffer. The default is no operation. For more
  information, see the XGL_WIN_RAS_BUF_DRAW reference page.

virtual void setBufDisplay(Xgl_usgn32)
  Specifies the current display buffer. This function maps to the API attribute
  XGL_WIN_RAS_BUF_DISPLAY and is used by the XGL device-independent
  code to set the current display buffer for the device. The default is no
  operation. For more information, see the XGL_WIN_RAS_BUF_DISPLAY.

virtual void setBufMinDelay(Xgl_usgn32)
  Defines the minimum time delay between buffer switches for this device.
  This function maps to the API attribute XGL_WIN_RAS_BUF_MIN_DELAY.
  The default is no operation. For more information, see the
  XGL_WIN_RAS_BUF_MIN_DELAY reference page.

virtual void setCmap(XglCmap*) Sets the color map. This function maps to the API attribute XGL_DEV_COLOR_MAP and is used by the XGL device-independent code to inform the pipeline when the XGL Color Map object changes. The input argument is a pointer to a Color Map object. The default is no operation.
When the contents of the Color Map change, XglDpDevWinRas::setCmap() is called. The device pipeline messageReceive() is called for object type XGL_WIN_RAS with message flag XGLI_MSG_DEV_COLOR. This message tells the device pipeline to handle the appropriate plane mask and color map changes.
virtual void setPixelMapping(conxt Xgl_usgn32[]) Sets the pixel mapping from the application's color indexes to the device color indexes. This function maps to the API attribute XGL_WIN_RAS_PIXEL_MAPPING and is used by the XGL device-independent code to inform the device when the pixel mapping changes. The input argument is an array of color values. The default is no operation. For more information, see the XGL_WIN_RAS_PIXEL_MAPPING reference page.
virtual void setStereoMode(Xgl_stereo_mode) Requests stereo mode support from the device. The input argument is an Xgl_stereo_mode enumerated value for the stereo setting. This function maps to the API attribute XGL_WIN_RAS_STEREO_MODE and is used by the XGL device-independent code to set the stereo mode on the device. The default is no operation. For more information, see the XGL_WIN_RAS_STEREO_MODE reference page.
virtual XglPixRectMem* getSwZBuffer() Returns a pointer to the XglPixRectMem object that represents the software Z-buffer. This function should be overridden by all devices that have a software implementation of the Z-buffer. The default return is NULL, which means that if the device has a hardware Z-buffer, it does not need to override this function.
virtual XglPixRectMem* getSwAccumBuffer() Returns a pointer to the XglPixRectMem object that represents the software accumulation buffer. This function should be overridden by all devices that have a software implementation of the accumulation buffer. The default return is NULL, which means that if the device has a hardware accumulation buffer, it does not need to override this function.
virtual Xgl_boolean needRtnDevice() Returns TRUE if the base device needs a shadow device for backing store. Device pipelines that provide for backing-store support in hardware override this function, as do Xlib or PEXlib pipelines that use backing-store support in the server.

Virtual Functions in DpDevMemRas.h


Note - For all practical purposes, there is only one Memory Raster pipeline, which is provided by XGL. The device pipeline does not need to override the functions in DpDevMemRas.h as they are overridden in XGL's Memory Raster pipeline.

virtual XglPixRectMem* getImageBufferPixRect()
  Returns a pointer to the XglPixRectMem object that represents the image
  buffer for the memory raster. The default return is NULL.

virtual XglPixRectMem* getZBufferPixRect()
  Returns a pointer to the XglPixRectMem object that represents the Z-buffer
  for the memory raster. The default return is NULL.

virtual XglPixRectMem* getAccumBufferPixRect()
  Returns a pointer to the XglPixRectMem object that represents the
  accumulation buffer for the memory raster.  The default return is NULL.

virtual Xgl_accum_depth getAccumBufferDepth()
  Returns a value for the depth of the accumulation buffer.  The default return
  value is XGL_ACCUM_DEPTH_2X.

virtual void setCmap(XglCmap*)
  Sets the color map. This function maps to the API attribute
  XGL_DEV_COLOR_MAP and is used by the XGL device-independent code to
  inform the pipeline when the XGL Color Map object changes. The input
  argument is a pointer to the Color Map object.

virtual void setImageBufferAddr(Xgl_usgn32*)
  Specifies the array of pixels used in an XGL Memory Raster. The default is
  no operation. This function maps to the API attribute
  XGL_MEM_RAS_IMAGE_BUFFER_ADDR. For more information, see the
  XGL_MEM_RAS_IMAGE_BUFFER_ADDR reference page.

virtual void setZBufferAddr(Xgl_usgn32*) Sets the starting address of the block of memory for the Z-buffer of a memory raster. The default is no operation. This function maps to the API attribute XGL_MEM_RAS_Z_BUFFER_ADDR. For more information, see the XGL_MEM_RAS_Z_BUFFER_ADDR reference page.
virtual void setLineBytes(Xgl_usgn32) Sets the linebytes value when the memory raster is set up to access memory for retained windows. linebytes is the number of bytes that separates one line in a raster, that is, the number of bytes from (x,y) to (x,y+1). The default is no operation.

Quick Reference Chart of Virtual Functions

In the device pipeline classes there are some virtual functions that your device pipeline must override and other functions that are optional. Whenever possible, XGL has provided defaults for functions; however, you will probably want to override XGL's version of these functions if your device can accelerate the functionality. Required functions are completely device dependent.
Table 3-6 provides a quick reference summary of all the pipeline functions; those marked "Required" must be overridden by the device pipeline, or an error will be returned.
Table 3-6
ClassFunction NameStatus
Device pipeline .so filexgli_create_PipeLib()Required
XglDpLibgetDpMgr()Required
XglDpMgrcreateDpDev()
inquire()
Required
Required
XglDpDevcreateDpCtx() for 2D
createDpCtx() for 3D
copyBuffer() for 2D
copyBuffer() for 3D
Required
Required
Required
Required
getDcOrientation()
getMaxZ()
getGammaValue()
Optional
Optional
Optional
XglDpDevRastersetRectList()
setRectNum()
setSourceBuffer()
setSwZBuffer()
setSwAccumBuffer()
syncRtnDevice()
All
optional
Table 3-6 (Continued)
ClassFunction NameStatus
XglDpDevWinRasgetDepth()
getAccumBufferDepth()
getRealColorType()
resize()
setBackingStore()
setBufDisplay()
setBufDraw()
setBufMinDelay()
setCmap()
setPixelMapping()
setStereoMode()
setBuffersRequested()
getSwZBuffer()
getSwAccumBuffer()
needRtnDevice()
All
optional
XglDpDevMemRasgetImageBufferPixRect() getZBufferPixRect() getAccumBufferPixRect() getAccumBufferDepth() setCmap()

setImageBufferAddr() setZBufferAddr() setLineBytes()

All optional
XglDpCtx2d
LI-1 Primitives

li1AnnotationText()
li1DisplayGcache()
li1MultiArc()
li1MultiCircle()
li1MultiMarker()
li1MultiPolyline()
li1MultiRectangle()
li1MultiSimplePolygon()
li1NurbsCurve()
li1Polygon()
li1StrokeText()

All
optional
Table 3-6 (Continued)
ClassFunction NameStatus
Pixel and Raster
Operators
li1NewFrame
li1CopyBuffer()
li1GetPixel()
li1Image()
li1SetMultiPixel()
li1SetPixel()
li1SetPixelRow()
li1Flush()
li1PickBufferFlush()
Required
Required
Required
Optional
Optional
Required
Optional
Optional
Optional
LI-2 Functionsli2GeneralPolygon
li2MultiDot()
li2MultiEllipse()
li2MultiEllipticalArc()
li2MultiPolyline()
li2MultiRect()
li2MultiSimplePolygon()
All
optional
LI-3 Functionsli3Begin()
li3End()
li3MultiDot()
li3Vector()
li3MultiSpan()
li3CopyFromDpBuffer()
li3CopyToDpBuffer()
All
required
State ChangesobjectSet()Required
Message PassingmessageReceive()Required
XglDpCtx3d LI-1 PrimitivesAll 2D primitives and the following: li1MultiEllipticalArc() li1NurbsSurf()

li1QuadrilateralMesh() li1TriangleList() li1TriangleStrip()

All optional
Pixel and Raster
Operators
All 2D pixel and raster functions and the
following:
li1Accumulate()
li1ClearAccumulation()


Optional
Optional
Table 3-6 (Continued)
ClassFunction NameStatus
LI-2 Functionsli2GeneralPolygon()
li2MultiDot()
li2MultiPolyline()
li2MultiSimplePolygon()
li2TriangleList()
li2TriangleStrip()
All
optional
LI-3 Functionsli3Begin()
li3End()
li3MultiDot()
li3Vector()
li3MultiSpan()
li3CopyFromDpBuffer()
li3CopyToDpBuffer()
All
required
State ChangesobjectSet()Required
Message PassingmessageReceive()Required