XIL Device Porting and Extensibility Guide
  Suchtext Nur in diesem Buch
Dieses Buch im PDF-Format herunterladen

I/O Devices

3

About I/O Devices

In the XIL Imaging Library, I/O devices include any devices that can generate or receive images, such as frame grabbers, image files, and displays. The XIL library supports these types of devices by allowing them to appear as device images to an application. When a device image is used as a source in an operation, an image is captured from the device. When a device image is used as a destination in an operation, an image is written to the device.
The I/O device handler provides an implementation for an image captured from a device and for an image written to a device. The first time a device image is created using the xil_create_from_device() API call, the software module containing the handler is loaded. Once the I/O handler is loaded, any compute devices that have only the I/O handler as a dependence are loaded. The I/O handler information is cached so that subsequent creations of new device images from the same device do not require reloading the I/O handler.
The character string representing the name of the device, passed as the second argument to xil_create_from_device(), is used to select the appropriate loadable library. Currently, the following API call attempts to load an I/O handler named /opt/SUNWits/Graphics-sw/xil/lib/pipelines/ xiliomy_device.so.1 and fails with an error if this loadable library does not exist:
device_image = xil_create_from_device(systemState, "iomy_device",
NULL);


Note - For I/O handlers that are frame buffers, the string returned by the ioctl call for VIS_GETINDENTIFIER must match the name of the loadable device handler. XIL prepends the unique string returned by this ioctl call with io. Therefore, XIL is looking for xiliovis_identifier.name.so.1. For more information about graphics device drivers and ioctl, see the man page for visual_io or the manual Writing Device Drivers.

XilDeviceInputOutputType Class

As described in Chapter 1, "Overview," the abstract class XilDeviceType is subclassed by the library to form the Type handler for each kind of handler the library supports. For I/O devices, the abstract class XilDeviceInputOutputType is defined (see Code Example 3-1). This class must be further subclassed to represent the particular I/O device type represented in the handler. Only one instantiation of this class exists for each type of I/O device created by the device-specific driver.
Code Example 3-1 Definition of XilDeviceInputOutputType Class

  #include "XilDeviceType.h"  
  class XilDeviceInputOutputType : public XilDeviceType {  
   public:  
   // This function is used to create instances of the input/output  
   // object.  
   virtual XilDeviceInputOutput* createDeviceInputOutput(  
       XilImage* parent, XilAttribute* attribs)=0;  
  
   // destructor. This should release all resources that were used to  
   // make the connection to the device.  
   virtual ~XilDeviceInputOutputType();  
  };  

When the handler is loaded, the library looks through the symbol table of the loadable library for a specific function that must exist in each I/O handler:
XilDeviceInputOutputType* XilCreateInputOutputType()

The library invokes this function, which is responsible for doing any global, one-time initialization of the device, and sets up any data that will be used by all instances of this I/O device. This derived "type" class must contain the function createDeviceInputOutput(), which creates each instance of the device class. This function is declared with an XilAttribute* parameter. The XilAttribute object is used for atomically setting multiple device attributes. See the section "The XilAttribute Class" in Chapter 1 for more information.
The section "Sample I/O Handler" on page 75 contains a derived type class XilDeviceInputOutputTypeCG6, which instantiates the device class XilDeviceInputOutputCG6. Likewise, the section "Sample I/O Device Handler" on page 106 contains a derived type class XilDeviceInputOutputTypeXlib, which instantiates the device class XilDeviceInputOutputXlib.

Handling Multiple Devices in an I/O Handler

The I/O "type" class (for example, XilDeviceInputOutputTypeCG6) is responsible for keeping track of multiple devices. This tracking is accomplished by the use of a linked list of descriptors. Each entry in the list describes a given device, and each frame buffer attached to the system has a descriptor. The descriptors have the same fields but different values. Each window, for example, created on a device (such as a frame buffer) is an instantiation of the device class. The class contains information that maps the device back to a descriptor entry in the linked list. Each device stores its own specific information (such as position/size on the screen). The example in the section "Sample I/O Handler" on page 75 illustrates these concepts.
Consider the case of a system with two CG6 frame buffers and a window on each:

  XilDeviceInputOutputTypeCG6  
       head-> descriptor_CG60         --+  
                                        |next  
                descriptor_CG61       <-+  
  instantiation 0  
  XilDeviceInputOutputCG6  
       window0  
           my_descriptor - descriptor_CG60  
           specifics of window0  
  instantiation 1  
  XilDeviceInputOutputCG6  
       window1  
           my_descriptor = descriptor_CG61  
           specifics of window1  

XilDeviceInputOutput Class

The handler creates a device specific class that derives from XilDeviceInputOutput. This is where all of the device-specific information pertaining to a particular instance of the I/O device is stored. For example, an X display object might store information about a display, window, and graphics context here. See Code Example 3-2 for the definition of the base XilDeviceInputOutput class. A new instance of this class must be created for each device image.
Code Example 3-2 Definition of XilDeviceInputOutput Class (1 of 3)

  //------------------------------------------------------------------------  
  //  
  // Description:  
  //  
  // The XilDeviceInputOutput class describes one instantiation of a  
  // particular input/output device. There can be many of these.  
  // See the example input/output driver for more information.  
  //  
  //------------------------------------------------------------------------  
  
  class XilDeviceInputOutput : public XilDevice {  

Code Example 3-2 Definition of XilDeviceInputOutput Class (2 of 3)

   public:  
  
   // set a device-specific attribute  
   virtual int setDeviceAttribute (char attribute_name[], void *value)=0;  
  
   // get (return a pointer to) a device-specific attribute.  
   virtual int getDeviceAttribute (char attribute_name[], void **value)=0;  
  
   // implement display on this input/output device  
   virtual void display (XilImage*)=0;  
  
   // implement capture on this input/output device  
   virtual void capture (XilImage*)=0;  
  
   // get and set particular image pixel values directly  
   // from/to the device  
   virtual void getPixel(unsigned short x, unsigned short y,  
          unsigned short band, unsigned short count,  
          float* data)=0;  
   virtual void setPixel(unsigned short x, unsigned short y,  
          unsigned short band, unsigned short count,  
          float* data)=0;  
  
   // return the pointer to the image the input/output device uses  
   // as its buffer to (display from / capture to)  
   XilImage* getParent ();  
  
   // return the XilImageType that should be returned from the  
   // xil_create_from_device() call  
   XilImageType* getImageType();  
  
   // return the actual XilImageType that is used internally.  
   // this may be different from the way it appears to the  
   // application. For example, the image type for a 24-bit  
   // frame buffer may be a 3-banded image, whereas the real  
   // image type would be a 4-band image to make the copy to  
   // the display faster.  
   XilImageType* getRealImageType();  
  
   // functions to indicate whether this device can be read from/  
   // written to  
   Xil_boolean isReadable ();  

Code Example 3-2 Definition of XilDeviceInputOutput Class (3 of 3)

   Xil_boolean isWritable ();  
  
   // return the op number of the display operation associated with this device  
   unsigned short getDisplayOpNumber();  
  
   // return the op number of the capture operation associated with this device  
   unsigned short getCaptureOpNumber();  
  
   // flag to indicate whether the buffer image contents are valid  
   // (if a molecule has been used to write directly to the display,  
   // for example, the buffer image is no longer valid)  
   Xil_boolean memoryIsValid();  
  
   // set the memory-valid bit  
   void setMemoryValid(Xil_boolean valid);  
  
   //destructor  
   virtual ~XilDeviceInputOutput();  
  
   protected:  
   XilImage*              parent;  
   XilImageType*          imageType;  
   XilImageType*          realImageType;  
   Xil_boolean            readable;  
   Xil_boolean            writeable;  
   unsigned short         displayOpNumber;  
   unsigned short         captureOpNumber;  
   Xil_boolean            memoryValid;  
  };  

Device Attribute Functions

I/O devices may define attributes that are used to modify or report their behavior. For example, a frame grabber would use attributes to allow the application to select the type of output image or to select which video input to use. A file input device would use attributes to set the path name.
setDeviceAttribute() takes an attribute and a value and performs the device-specific function that the attribute defines.
getDeviceAttribute() returns the value associated with the given device-specific attribute.
getPixel() returns pixel information for the I/O device.
setPixel() sets the device pixel to the given value.
display() causes the parent image to be copied to the device.
capture() causes the device to copy data into the parent image.
Device image attributes are defined by the port, but some frame-buffer-specific attributes have already been defined by the standard handlers. These attributes are listed in Table 3-1:
Table 3-1
AttributeValue
XCOLORMAPThe X colormap of the device image (write only)
WINDOWThe X window (read only)
DISPLAYThe X display (read only)
Future releases of the XIL library will suggest common attributes for camera-like I/O devices; other I/O devices such as files and printers will have other attributes.

Parent Function

The parent member is the image that holds the results of the capture and the source of the display. When a device image is used as a source, the library inserts a device-dependent capture into the current operation sequence and returns the parent image. When a device image is used as a destination, the library inserts a copy from the source to the parent image and then inserts a display operation into the current operation sequence. The parent is created by the XIL library and is passed to the constructor for the XilDeviceInputOutput subclass. The parent is primarily used in the constructor of the derived XilDeviceInputOutput class to set up the image type of the device image that is stored in imageType.

Image Type Functions

The imageType member holds the image type of the device image. The imageType describes the size, number of bands, and data type of the image that is required or will be generated by the device image. The imageType is
created by the handler using the createImageType() member of the system state. Sometimes, it is necessary to return to the application an imageType different from the actual description of the device. For example, the imageType for a 24-bit frame buffer may be a 3-banded image, but the true imageType is a 4-band image. The realImageType member holds the description of the actual device; normally, the imageType is the same as the
realImageType.
realImageType = imageType = parent->getSystemState()->
             createImageType(xsize,ysize,nbands,datatype);

Read- and Write-Only Functions

The readable and writeable members allow a device to appear as read-only or write-only. If the handler wishes for a device to be read-only, these members can be set appropriately when the class is created.

Op Number Functions

The members displayOpNumber and captureOpNumber are ordinals that describe the type of operation. They provide a unique reference to the specific capture or display operation in order for it to be placed into the DAG. The displayOpNumber and captureOpNumber members are assigned automatically when the I/O handler is loaded and the device type is created. The number (opcode) is keyed from the function names display_devicename and capture_devicename, where devicename is the name of the I/O device handler. Each device class instantiation must request and store these opcodes. The opcodes are obtained by using the XilLookupOpNumber() function with the appropriate keyname. Shown next is the action for the device ioSUNWcg6:
displayOpNumber = XilLookupOpNumber("display_ioSUNWcg6");
captureOpNumber = XilLookupOpNumber("capture_ioSUNWcg6");

XilLookupOpNumber() also is used for compute handlers. See Chapter 4, "Compute Devices," for more information.
When a device image is the destination or source of an operation, the library inserts a display or capture operation into the current operation sequence of the DAG. The core uses the getDisplayOpNumber and getCaptureOpNumber member functions to extract the operation number.

Adding an I/O Device

Adding an I/O device is straightforward in the XIL library. The handler writer must follow these steps:
  1. Implement the XilCreateDeviceInputOutput() function. It must create an instance of the derived XilDeviceInputOutputType class.

  2. Implement the XilDeviceInputOutputType class to provide device creation and initialization. Place all common information for all instances of the device in this class.

  3. Implement the XilDeviceInputOutput class for the device, including capture(), display(), get/setPixel(), as well as get/setDeviceAttribute() if needed.

  4. Place the new loadable library file in an application package so that it will be installed in the correct location. See the document SunOS Application Packaging and Installation Guide for information on using the package system. Also see Chapter 1, "Overview," for information about packaging handlers.

    The name of the loadable library must be unique; we strongly suggest using the name xiliodevice_name.so, where device_name is the name that will be used to describe the device in the xil_create_from_device() API call. The first part of the device_name should be a unique identifier for the company producing the handler; for example, all Sun I/O handlers should contain the string SUNW as the first part of the device name.

Sample I/O Handler

This section shows an example I/O device handler that treats a SPARC GX frame-buffer window as an I/O device. It's an important example because it illustrates how to write an I/O handler that talks directly to hardware using DGA (Direct Graphics Access). The files for the GX example are located in directory /opt/SUNWddk/ddk_2.4/xil/src/cg6_device_handler.
A parallel example for an x86-specific module treats a p9000 frame-buffer window as an I/O device. The p9000 example isn't shown in this manual because the p9000 architecture is similar to the CG6 architecture. The p9000 code is included to demonstrate some of the differences you can expect when writing an XIL module for x86. The files for the p9000 example are located in directory /opt/SUNWddk/ddk_2.4/xil/src/p9000.
The GX example shown below has four files:
  • XilDeviceInputOutputTypeCG6.h
  • XilDeviceInputOutputTypeCG6.cc
  • XilDeviceInputOutputCG6.h
  • XilDeviceInputOutputCG6.cc
The p9000 example, not shown but located in directory /opt/SUNWddk/ddk_2.4/xil/src/p9000, also has four files:
  • XilDeviceInputOutputTypeP9000.h
  • XilDeviceInputOutputTypeP9000.cc
  • XilDeviceInputOutputP9000.h
  • XilDeviceInputOutputP9000.cc

XilDeviceInputOutputTypeCG6.h

Code Example 3-3 XilDeviceInputOutputTypeCG6.h

  //This line lets emacs recognize this as -*- C++ -*- Code  
  //------------------------------------------------------------------------  
  //  
  //  File:        XilDeviceInputOutputTypeCG6.h  
  //  Project:     XIL  
  //  Created:     93/08/20  
  //  RespEngr:    John L. Furlani  
  //  Revision:    1.1  
  //  Last Mod:    18:14:19, 07 Sep 1993  
  //  
  //  Description:  
  //    This file contains the description of the CG6 device type  
  //    class.  The device type is created once for each instance of XIL  
  //    -- not on a per-window basis.  It contains all of the device  
  //    information which does not change from window-to-window (like  
  //    the device mapping).  
  //  
  //------------------------------------------------------------------------  
  #pragma ident    "@(#)XilDeviceInputOutputTypeCG6.h1.1\t93/09/07  "  
  
  #ifndef XILDEVICEINPUTOUTPUTTYPECG6  
  #define XILDEVICEINPUTOUTPUTTYPECG6  
  
  #include <stdlib.h>  
  #include <sys/cg6fbc.h>  
  #include <X11/Xlib.h>  
  #include <X11/Xutil.h>  
  #include <xil/XilDeviceInputOutputType.h>  
  #include <xil/XilError.h>  
  #include <dga/dga.h>  
  
  //  
  //  A structure that describes a mapping of a CG6 device.  Only one  
  //  mapping is created for all of the windows on the screen.  A list  
  //  is kept where each node represents a single mapping of a different  
  //  CG6 device.  
  //  
  struct CG6Description {  
     int            fd;  
     unsigned char* fb_mem;  

Code Example 3-3 XilDeviceInputOutputTypeCG6.h (Continued)

     int            fb_height;  
     int            fb_width;  
     int            fb_size;  
     fbc*           fb_fbc;  
     char name[32];  
     struct CG6Description* next;  
  };  
  
  class XilDeviceInputOutputTypeCG6 : public XilDeviceInputOutputType {  
  public:  
      //  
      //  The routine called by the XIL core to create the device type.  
      //  
      virtual XilDeviceInputOutput* createDeviceInputOutput(XilImage* parent,  
                                                            void*     data);  
  
      //  
      //  Our constructors and destructors...  
      //  
      XilDeviceInputOutputTypeCG6();  
      ~XilDeviceInputOutputTypeCG6();  
  
      //  
      //  This routine returns a full description of the given CG6  
      //  device.  A list of CG6 descriptions is kept in this class so  
      //  multiple windows on the same device will not have multiple  
      //  mappings.  
      //  
      CG6Description* getCG6Description(char* device_name);  
  
  private:  
      //  
      //  The CG6 description list...  
      //  
      CG6Description* baseCG6Description;  
  };  
  
  #endif  

XilDeviceInputOutputTypeCG6.cc

Code Example 3-4 XilDeviceInputOutputTypeCG6.cc (1 of 6)

  //This line lets emacs recognize this as -*- C++ -*- Code  
  //------------------------------------------------------------------------  
  //  
  //  File:        XilDeviceInputOutputTypeCG6.cc  
  //  Project:     XIL  
  //  Created:     93/08/20  
  //  RespEngr:    John L. Furlani  
  //  Revision:    1.1  
  //  Last Mod:    18:14:28, 07 Sep 1993  
  //  
  //------------------------------------------------------------------------  
  #pragma ident    "@(#)XilDeviceInputOutputTypeCG6.cc1.1\t93/09/07  "  
  
  #include <sys/fbio.h>  
  #include <sys/cg6reg.h>  
  #include <sys/mman.h>  
  
  #include "XilDeviceInputOutputTypeCG6.h"  
  #include "XilDeviceInputOutputCG6.h"  
  
  //  
  //  The XIL core calls this routine when opening this I/O pipeline to  
  //  create the DeviceInputOutputType for the CG6 device.  
  //  
  XilDeviceInputOutputType *XilCreateInputOutputType()  
  {  
      return(new XilDeviceInputOutputTypeCG6());  
  }  
  
  XilDeviceInputOutputTypeCG6::XilDeviceInputOutputTypeCG6()  
  {  
      //  
      //  Initialize the list of CG6 description structure to NULL  
      //  
      baseCG6Description=NULL;  
  }  
  
  XilDeviceInputOutputTypeCG6::~XilDeviceInputOutputTypeCG6()  
  {  
      CG6Description* temp = baseCG6Description;  

Code Example 3-4 XilDeviceInputOutputTypeCG6.cc (2 of 6)

      while(baseCG6Description) {  
          baseCG6Description = baseCG6Description->next;  
          delete temp;  
          temp = baseCG6Description;  
      }  
  }  
  
  //  
  //  The XIL core calls this routine when the user calls  
  //  xil_create_from_window() with an X window that resides on a CG6.  
  //  For every display window the user opens, this routine is called  
  //  a new instantiation of XilDeviceInputOutputCG6 is created.  
  //  
  XilDeviceInputOutput*  
  XilDeviceInputOutputTypeCG6::createDeviceInputOutput(XilImage* parent,  
                                                       void*     data)  
  {  
      //  
      //  Create an instantiation of the DeviceInputOutput for this  
      //    window.  
      //  
      XilDeviceInputOutputCG6* device = new XilDeviceInputOutputCG6(parent,data);  
      if(device==NULL) {  
          XIL_ERROR(NULL,XIL_ERROR_RESOURCE,"di-1",TRUE);  
          return NULL;  
      }  
  
      //  
      //  Check that it was created successfully by getting the  
      //    ImageType which is set in the constructor.  
      //  
      if(device->getImageType()==NULL) {  
          XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-1",TRUE);  
          delete device;  
          return NULL;  
      }  
  
      return device;  
  }  
  
  //  
  //  The routine that creates and manages the CGDescription list with a  

Code Example 3-4 XilDeviceInputOutputTypeCG6.cc (3 of 6)

  //    single node entry per CG6 device on the system.  
  //  
  CG6Description*  
  XilDeviceInputOutputTypeCG6::getCG6Description(char* name)  
  {  
     //  
     //  Look through the list to determine if the device has already  
     //  been opened.  
     //  
     CG6Description* tmp = baseCG6Description;  
     while(tmp) {  
         if(strcmp(name, tmp->name)==NULL) {  
             return tmp;  
         }  
         tmp = tmp->next;  
     }  
  
     //  
     //  Well, this device hasn't opened yet so we'll go ahead and  
     //  create a new description.  
     //  
     CG6Description* description= new CG6Description;  
     if(!description) {  
         XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-1",TRUE);  
         return NULL;  
     }  
     strcpy(description->name,name);  
  
     //  
     //  Now we actually open the device and get its attributes.  
     //  
     description->fd = open(description->name, O_RDWR);  
     if(description->fd < 0) {  
         XIL_ERROR(NULL,XIL_ERROR_RESOURCE,"di-212",TRUE);  
         delete description;  
         return NULL;  
     }  
  
     //  
     //  Get the device attributes.  
     //  
     struct fbgattr attr;  

Code Example 3-4 XilDeviceInputOutputTypeCG6.cc (4 of 6)

     if(ioctl(description->fd, FBIOGATTR, &attr) < 0) {  
         XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-213",TRUE);  
         delete description;  
         return NULL;  
     }  
  
     //  
     //  Be certain the device is really a CG6.  
     //  
     if(attr.real_type != FBTYPE_SUNFAST_COLOR) {  
         //  
         //  Somehow we were called on a non-CG6 framebuffer.  
         //    Definite error.  
         //  
         XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-214",TRUE);  
         delete description;  
         return NULL;  
     }  
  
     //  
     //  Get the information describing the CG6 from the FBIOGXINFO  
     //  ioctl call.  
     //  
     cg6_info cg6_information;  
     if(ioctl(description->fd, FBIOGXINFO, &cg6_information) < 0) {  
         XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-213",TRUE);  
         delete description;  
         return NULL;  
     }  
  
     //  
     //  Fill our description of the CG6.  
     //  
     description->fb_width  = cg6_information.accessible_width;  
     description->fb_height = cg6_information.accessible_height;  
     description->fb_size   = cg6_information.vmsize*1024*1024;  
  
     //  
     //  Get the register mappings.  
     //  
     description->fb_fbc = (fbc*)  
         mmap(NULL, CG6_FBCTEC_SZ, PROT_READ|PROT_WRITE, MAP_PRIVATE,  

Code Example 3-4 XilDeviceInputOutputTypeCG6.cc (5 of 6)

              description->fd, CG6_VADDR_FBCTEC);  
     if(description->fb_fbc == (fbc*) -1) {  
         XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-215",TRUE);  
         delete description;  
         return NULL;  
     }  
  
     //  
     //  Map the framebuffer itself  
     //  
     description->fb_mem = (Xil_unsigned8*)  
         mmap(NULL, description->fb_size, PROT_READ|PROT_WRITE, MAP_SHARED,  
              description->fd, CG6_VADDR_COLOR);  
     if(description->fb_mem == (Xil_unsigned8*) -1) {  
         XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-215",TRUE);  
         munmap((caddr_t)description->fb_fbc, CG6_FBCTEC_SZ);  
         delete description;  
         return NULL;  
     }  
  
     //  
     //  Wait to ensure the GX is idle and ready for us to set some  
     //  registers.  
     //  
     while(description->fb_fbc->l_fbc_status & L_FBC_BUSY);  
  
     //  
     //  Initialize the registers to what we want done.  
     //  
     description->fb_fbc->l_fbc_misc.l_fbc_misc_blit=L_FBC_MISC_BLIT_NOSRC;  
     description->fb_fbc->l_fbc_misc.l_fbc_misc_data=L_FBC_MISC_DATA_COLOR8;  
     description->fb_fbc->l_fbc_misc.l_fbc_misc_draw=L_FBC_MISC_DRAW_RENDER;  
     description->fb_fbc-  
  >l_fbc_misc.l_fbc_misc_bwrite0=L_FBC_MISC_BWRITE0_ENABLE;  
     description->fb_fbc-  
  >l_fbc_misc.l_fbc_misc_bwrite1=L_FBC_MISC_BWRITE1_DISABLE;  
     description->fb_fbc->l_fbc_misc.l_fbc_misc_bread=L_FBC_MISC_BREAD_0;  
     description->fb_fbc->l_fbc_planemask= 0xff;  
     description->fb_fbc->l_fbc_pixelmask= 0xffffffff;  
     description->fb_fbc->l_fbc_clipcheck= 0;  
     description->fb_fbc->l_fbc_rasteroffx= 0;  
     description->fb_fbc->l_fbc_rasteroffy=0;  

Code Example 3-4 XilDeviceInputOutputTypeCG6.cc (6 of 6)

     description->fb_fbc->l_fbc_autoincx= 0;  
     description->fb_fbc->l_fbc_autoincy= 0;  
  
     //  
     //  Add the newly created description to our description list and  
     //    return the new description to the caller.  
     //  
     description->next= baseCG6Description;  
     baseCG6Description= description;  
  
     return description;  
  }  

XilDeviceInputOutputCG6.h

Code Example 3-5 XilDeviceInputOutputCG6.h (1 of 3)

  //This line lets emacs recognize this as -*- C++ -*- Code  
  //-----------------------------------------------------*-------------------  
  //  
  //  File:        XilDeviceInputOutputCG6.h  
  //  Project:     XIL  
  //  Created:     93/08/20  
  //  RespEngr:    John L. Furlani  
  //  Revision:    1.1  
  //  Last Mod:    18:13:44, 07 Sep 1993  
  //  
  //  Description:  
  //    This file contains the device instantiation-specific  
  //    information for the CG6 device.  This object is created on a  
  //    per-displayimage basis by the XIL core.  It is responsible for  
  //    the per-window access to the CG6 device.  This includes  
  //    display/capture/setPixel/getPixel.  
  //  
  //------------------------------------------------------------------------  
  #pragma ident    "@(#)XilDeviceInputOutputCG6.h1.1\t93/09/07  "  
  
  #ifndef XILDEVICEINPUTOUTPUTCG6  
  #define XILDEVICEINPUTOUTPUTCG6  
  
  #include <stdlib.h>  
  #include <sys/cg6reg.h>  
  #include <sys/cg6fbc.h>  
  #include <X11/Xlib.h>  
  #include <X11/Xutil.h>  
  #include <xil/XilDeviceInputOutput.h>  
  #include <xil/XilError.h>  
  #include <dga/dga.h>  
  
  class XilDeviceInputOutputCG6 : public XilDeviceInputOutput {  
  public:  
      //  
      //  Set and get CG6 device-specific attributes  
      //  
      virtual int setDeviceAttribute(char attribute_name[], void* value);  
      virtual int getDeviceAttribute(char attribute_name[], void**);  

Code Example 3-5 XilDeviceInputOutputCG6.h (2 of 3)

      //  
      //  The display routine which copies the entire XIL image backing  
      //  store to the display.  And, the capture routine which updates  
      //  the XIL image backing store with what's actually on the display.  
      //  
      virtual void display(XilImage*);  
      virtual void capture(XilImage*);  
  
      //  
      //  The single-pixel operations to just modify a few pixels.  
      //  
      virtual void getPixel(unsigned short x, unsigned short y,  
                            unsigned short band, unsigned short count,  
                            float *data);  
      virtual void setPixel(unsigned short x, unsigned short y,  
                            unsigned short band, unsigned short count,  
                            float *data);  
  
      //  
      //  The constructor and destructor.  
      //  
      XilDeviceInputOutputCG6(XilImage* parent, void* data);  
      virtual ~XilDeviceInputOutputCG6();  
  
      //  
      //  Our publicly available data which describes the window  
      //  
      Display* displayptr;  
      Window window;  
      Dga_window infop;  
      short* cliplist;  
      int win_x,win_y,win_width,win_height;  
      int fd;  
  
      //  
      //  Colormap Installation Info  
      //  
      Dga_cmap dga_cmap;  
      Colormap xcmap;  
  
      //  
      //   This flag indicates whether we're on a machine that  

Code Example 3-5 XilDeviceInputOutputCG6.h (3 of 3)

      //   only has CG6 display devices that can use the double  
      //   loads and stores  
      //  
      Xil_boolean    doubleLoadnStore;  
  
      //  
      //  CG6 Specific Info  
      //  
      short          fb_width;  
      short          fb_height;  
      int            fb_size;  
      unsigned char* fb_mem;  
      fbc*           fb_fbc;  
      int            fhc_config;  
      int*           dac_base;  
      int*           tec_base;  
      cg6_cmap*      cg6cmap;  
  };  
  
  #endif  

XilDeviceInputOutputCG6.cc

Code Example 3-6 XilDeviceInputOuputCG6.cc (1 of 18)

  //This line lets emacs recognize this as -*- C++ -*- Code  
  //------------------------------------------------------------------------  
  //  
  //  File:XilDeviceInputOutputCG6.cc  
  //  Project:XIL  
  //  Created:93/08/20  
  //  RespEngr:John L. Furlani  
  //  Revision:1.1  
  //  Last Mod:18:13:49, 07 Sep 1993  
  //  
  //------------------------------------------------------------------------  
  #pragma ident"@(#)XilDeviceInputOutputCG6.cc1.1\t93/09/07  "  
  
  #include <sys/utsname.h>  
  #include <sys/mman.h>  
  #include <X11/Xlib.h>  
  #include <xil/xilwindow.h>  
  #include <xil/XilImage.h>  
  #include <xil/XilOp.h>  
  #include <xil/XilRoi.h>  
  #include <xil/XilRoiList.h>  
  #include <xil/XilColorDefines.h>  
  #include <xil/xil_memcpy.h>  
  
  #include "XilDeviceInputOutputTypeCG6.h"  
  #include "XilDeviceInputOutputCG6.h"  
  
  XilDeviceInputOutputCG6::XilDeviceInputOutputCG6(XilImage* parent,  
                                                   void*     data)  
  {  
      //  
      //  Initialize the imageType to NULL to indicate the creation of  
      //    this device has not succeeded.  
      //  
      imageType = NULL;  
  
      //  
      //  Store a pointer to my parent...  
      //  

Code Example 3-6 XilDeviceInputOuputCG6.cc (2 of 18)

      this->parent = parent;  
  
      //  
      //  The CG6 is both readable and writeable.  
      //  
      readable = writeable = TRUE;  
  
      //  
      //  Determine if this machine has a sun4 architecture or not.  If  
      //  it is a sun4 architecture, then we must use the plain memcpy()  
      //  because CG6's on the sun4 architecture are connected to the P4  
      //  bus which does not support double loads and stores.  Otherwise,  
      //  we've got an SBus based CG6.  
      //  
      struct utsname uname_info;  
      if(uname(&uname_info) == -1) {  
          XIL_ERROR(NULL, XIL_ERROR_SYSTEM, "di-315", TRUE);  
          return;  
      }  
      if(!strcmp(uname_info.machine, "sun4")) {  
          doubleLoadnStore = FALSE;  
      } else {  
          doubleLoadnStore = TRUE;  
      }  
  
      //  
      //  Indicate to the XIL core that the memory version of the window  
      //  is currently not valid which means a capture is required if  
      //  someone tries to read from the display image.  
      //  
      memoryValid = FALSE;  
  
      //  
      //  Initialize the colormap variables for this window.  The xcmap  
      //  and the dga_cmap are initially set to NULL vales to indicate  
      //  that the user has not set the X_COLORMAP device attribute.  
      //  The colormap information is initialized each time the user  
      //  calls X_COLORMAP.  
      //  
      xcmap = 0;  
      dga_cmap = NULL;  

Code Example 3-6 XilDeviceInputOuputCG6.cc (3 of 18)

      //  
      //  Save the X Display and the X Window  
      //  
      XilWindow* xil_window = (XilWindow*)data;  
  
      this->displayptr = xil_window->display;  
      this->window     = xil_window->window;  
  
      //  
      //  Here we connect to DGA and turn the window we've been given  
      //    into a DGA window so we can access the hardware directly.  
      //  
      int dga_token = XDgaGrabWindow(xil_window->display, xil_window->window);  
      if(dga_token == NULL) {  
          XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-219",TRUE);  
          return;  
      }  
  
      if((infop = ((Dga_window) dga_win_grab(-1, dga_token))) == NULL) {  
          XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-219",TRUE);  
          XDgaUnGrabWindow(xil_window->display, xil_window->window);  
          return;  
      }  
  
      //  
      //  Get a pointer to the CG6 type so I can get the information  
      //    about the device my window is on.  
      //  
      XilDeviceInputOutputTypeCG6* io_cg6_type = (XilDeviceInputOutputTypeCG6*)  
          xil_global_state->getDeviceInputOutputType("ioSUNWcg6");  
      if(io_cg6_type == NULL) {  
          XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-188",FALSE);  
          return;  
      }  
  
      //  
      //  Create or get the already created device information from the  
      //    CG6 type.  
      //  
      CG6Description* cg6_description =  
          io_cg6_type->getCG6Description(dga_win_fbname(infop));  

Code Example 3-6 XilDeviceInputOuputCG6.cc (4 of 18)

      if(!cg6_description) {  
          //  
          //  TODO: generate an appropriate error  
          //  
          return;  
      }  
  
      //  
      //  Initialize our own variables.  
      //  
      this->fd        = cg6_description->fd;  
      this->fb_width  = cg6_description->fb_width;  
      this->fb_height = cg6_description->fb_height;  
      this->fb_mem    = cg6_description->fb_mem;  
      this->fb_fbc    = cg6_description->fb_fbc;  
  
      //  
      //  Determine what the imageType is going to be for this XIL  
      //    display image.  
      //  
      Window       root_window;  
      unsigned int x_depth;  
      unsigned int height;  
      unsigned int width;  
      int          x,y;  
      unsigned int border_width;  
      Status status = XGetGeometry(displayptr,  
                                   this->window,  
                                   &root_window,  
                                   &x, &y,  
                                   &width, &height,  
                                   &border_width, &x_depth);  
      if(status == 0) {  
          XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-220",TRUE);  
          return;  
      }  
  
      //  
      //  For the CG6 the imageType and the realImageType are the same.  
      //  
      imageType = realImageType =  
          parent->getSystemState()->createImageType(width,height,1,XIL_BYTE);  

Code Example 3-6 XilDeviceInputOuputCG6.cc (5 of 18)

      if(imageType == NULL) {  
          XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-188",FALSE);  
          return;  
      }  
  
      //  
      //  Lookup and cache the display and capture op numbers.  
      //  
      displayOpNumber = XilLookupOpNumber("display_ioSUNWcg6");  
      captureOpNumber = XilLookupOpNumber("capture_ioSUNWcg6");  
  }  
  
  XilDeviceInputOutputCG6::~XilDeviceInputOutputCG6()  
  {  
     dga_win_ungrab(infop, 1);  
     XDgaUnGrabWindow(displayptr,window);  
     if (imageType) imageType->destroy();  
  }  
  
  void  
  XilDeviceInputOutputCG6::setPixel(unsigned short x,  
                                    unsigned short y,  
                                    unsigned short,  
                                    unsigned short,  
                                    float*         data)  
  {  
      //  
      //  Lock the DGA window so I can access the framebuffer.  
      //  
      DGA_WIN_LOCK(infop);  
  
      //  
      //  We grab the cliplist every time since checking it may have  
      //  cause problems with molecules that go directly to the display  
      //  which need to know if the window has been modified.  It's  
      //  cheap enough.  
      //  
      cliplist = dga_win_clipinfo(infop);  
      dga_win_bbox(infop, &win_x, &win_y, &win_width, &win_height);  
  
      //  
      //  Transform the point into screen space.  

Code Example 3-6 XilDeviceInputOuputCG6.cc (6 of 18)

      //  
      y = y+win_y;  
      x = x+win_x;  
  
      //  
      //  Loop over the cliplist to figure out which rectangle contains  
      //  the pixel we're looking for.  
      //  
      while(*cliplist != DGA_Y_EOL) {  
          if((y >= (unsigned short)cliplist[0]) &&  
             (y <= (unsigned short)cliplist[1])) {  
              cliplist += 2;  
              while(*cliplist != DGA_X_EOL) {  
                  if((x >= (unsigned short)cliplist[0]) &&  
                     (x <= (unsigned short)cliplist[1])) break;  
                  cliplist += 2;  
              }  
              if(*cliplist != DGA_X_EOL) break;  
              cliplist++;  
          } else {  
              cliplist += 2;  
              while(*cliplist != DGA_X_EOL) cliplist += 2;  
              cliplist++;  
          }  
      }  
  
      if(*cliplist != DGA_Y_EOL) {  
          //  
          //  Set the pixel now that we've found the right rectangle on  
          //    the screen.  
          //  
          Xil_unsigned8* dst = fb_mem + y*fb_width + x;  
  
          //  
          //  Round the pixel up.  
          //  
          float value = data[0] + .5;  
  
          //  
          //  Clip the value properly and set it on the screen.  
          //  
          if(value > 255.0) {  

Code Example 3-6 XilDeviceInputOuputCG6.cc (7 of 18)

              *dst = 255;  
          } else if (value < 0.0) {  
              *dst = 0;  
          } else {  
              *dst = (unsigned char) value;  
          }  
      }  
  
      //  
      //  Unlock the window...  
      //  
      DGA_WIN_UNLOCK(infop);  
  }  
  
  void XilDeviceInputOutputCG6::getPixel(unsigned short x,  
                                         unsigned short y,  
                                         unsigned short,  
                                         unsigned short,  
                                         float*         data)  
  {  
      //  
      //  Lock the DGA window so I can access the framebuffer.  
      //  
      DGA_WIN_LOCK(infop);  
  
      //  
      //  We grab the cliplist every time since checking it may have  
      //  cause problems with molecules that go directly to the display  
      //  which need to know if the window has been modified.  It's  
      //  cheap enough.  
      //  
      cliplist = dga_win_clipinfo(infop);  
      dga_win_bbox(infop, &win_x, &win_y, &win_width, &win_height);  
  
      //  
      //  Transform the point into screen space.  
      //  
      y = y + win_y;  
      x = x + win_x;  

Code Example 3-6 XilDeviceInputOuputCG6.cc (8 of 18)

      //  
      //  Loop over the cliplist to figure out which rectangle contains  
      //  the pixel we're looking for.  
      //  
      while(*cliplist != DGA_Y_EOL) {  
          if((y >= (unsigned short)cliplist[0]) &&  
             (y <= (unsigned short)cliplist[1])) {  
              cliplist += 2;  
              while(*cliplist != DGA_X_EOL) {  
                  if((x >= (unsigned short)cliplist[0]) &&  
                     (x <= (unsigned short)cliplist[1])) break;  
                  cliplist += 2;  
              }  
              if(*cliplist != DGA_X_EOL) break;  
              cliplist++;  
          } else {  
              cliplist += 2;  
              while(*cliplist != DGA_X_EOL) cliplist += 2;  
              cliplist++;  
          }  
      }  
  
      if(*cliplist != DGA_Y_EOL) {  
          //  
          //  Return what's on the screen.  
          //  
          Xil_unsigned8* src = fb_mem + y*fb_width + x;  
          *data = *src;  
      } else {  
          //  
          //  Data point is obscured by another window so return 0.0  
          //  
          *data = 0.0;  
      }  
  
      //  
      //  Unlock the window...  
      //  
      DGA_WIN_UNLOCK(infop);  
  }  

Code Example 3-6 XilDeviceInputOuputCG6.cc (9 of 18)

  void  
  XilDeviceInputOutputCG6::display(XilImage* copy_image)  
  {  
      //  
      //  NOTE: There is code elsewhere which depends on this function handling  
      //        any arbitrary 1-band XIL_BYTE image.  
      //  
  
      //  
      //  Get the image origin and the child offsets.  
      //  
      long x_origin, y_origin;  
      copy_image->getOrigin(&x_origin,&y_origin);  
  
      unsigned int offset_x,offset_y,offset_band;  
      copy_image->getChildOffsets(&offset_x,&offset_y,&offset_band);  
  
      //  
      //  Get the memory for the XIL image backing store.  
      //  
      XilMemoryStorageByte* storage =  
          (XilMemoryStorageByte*)copy_image->getMemoryStorage();  
      if(storage == NULL) {  
          XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-140",FALSE);  
          return;  
      }  
  
      //  
      //  Get any ROIs associated with the display image.  
      //  
      XilRoi* roi = copy_image->getPixelsTouchedRoi();  
      if(roi == NULL) {  
          XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-6",FALSE);  
          return;  
      }  
  
      //  
      //  Lock the DGA window for our use.  
      //  
      DGA_WIN_LOCK(infop);  

Code Example 3-6 XilDeviceInputOuputCG6.cc (10 of 18)

      //  
      //  We grab the cliplist every time since checking it may  
      //  cause problems with codec molecules that go directly to the  
      //  display which need to know if the window has been modified.  
      //  It's cheap enough to not worry.  
      //  
      cliplist = dga_win_clipinfo(infop);  
      dga_win_bbox(infop, &win_x, &win_y, &win_width, &win_height);  
  
      //  
      //  Intersect the ROI list and the window cliplist to generate the  
      //  actual ROI of pixels we will touch on the display.  
      //  
      XilRoi* clipped_roi = roi->intersect(cliplist,  
                                           (int)(win_x+x_origin+offset_x),  
                                           (int)(win_y+y_origin+offset_y));  
      if(clipped_roi == NULL) {  
          XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-7",FALSE);  
          DGA_WIN_UNLOCK(infop);  
          return;  
      }  
  
      //  
      //  Get the ROI as a list of rectangles...  
      //  
      XilRoiList* roi_list = clipped_roi->getRectList();  
      if(roi_list == NULL) {  
          XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-8",FALSE);  
          return;  
      }  
  
      //  
      //  Take into account the child offsets  
      //  
      win_x += offset_x;  
      win_y += offset_y;  
  
      //  
      //  Operate over each rectangle.  The rectangles are guaranteed  
      //  not to go out outside of the image.  
      //  

Code Example 3-6 XilDeviceInputOuputCG6.cc (11 of 18)

      unsigned int   x_size, y_size;  
      long           x, y;  
      unsigned char* src;  
      unsigned char* dst;  
      while(roi_list->next(&x,&y,&x_size,&y_size)) {  
          //  
          //  All of the rectangles must be adjusted by  
          //    the image origin.  
          //  
          x += x_origin;  
          y += y_origin;  
  
          src = storage->data +  
              y*storage->scanline_stride +  
              x*storage->pixel_stride;  
  
          dst = fb_mem +  
              (win_y+y)*fb_width +  
              (win_x+x);  
  
          //  
          //  If this CG6 supports double loads and stores, then we can  
          //    use xil_memcpy() to put the data onto the screen.  
          //    Otherwise, we must use the plain memcpy() which does not  
          //    accelerate the copy by using double loads and stores.  
          //  
          if(doubleLoadnStore == TRUE) {  
              for(int i = 0; i<y_size; i++) {  
                  xil_memcpy(dst,src,x_size);  
  
                  dst += fb_width;  
                  src += storage->scanline_stride;  
              }  
          } else {  
              for(int i = 0; i<y_size; i++) {  
                  memcpy(dst,src,x_size);  
  
                  dst += fb_width;  
                  src += storage->scanline_stride;  
              }  
          }  
      }  

Code Example 3-6 XilDeviceInputOuputCG6.cc (12 of 18)

      //  
      //  Unlock the DGA window.  
      //  
      DGA_WIN_UNLOCK(infop);  
  
      //  
      //  Destroy all of the ROIs I created.  
      //  
      clipped_roi->destroy();  
      roi_list->destroy();  
  }  
  
  void  
  XilDeviceInputOutputCG6::capture(XilImage* copy_image)  
  {  
      //  
      //  Get the image origin and the child offsets.  
      //  
      long x_origin, y_origin;  
      copy_image->getOrigin(&x_origin,&y_origin);  
  
      unsigned int offset_x,offset_y,offset_band;  
      copy_image->getChildOffsets(&offset_x,&offset_y,&offset_band);  
  
      //  
      //  Get the memory for the XIL image backing store.  
      //  
      XilMemoryStorageByte* storage =  
          (XilMemoryStorageByte*)copy_image->getMemoryStorage();  
      if(storage == NULL) {  
          XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-140",FALSE);  
          return;  
      }  
  
      //  
      //  Get any ROIs associated with the display image.  
      //  
      XilRoi* roi = copy_image->getImageSpaceRoi();  
      if(roi == NULL) {  
          XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-6",FALSE);  
          return;  
      }  

Code Example 3-6 XilDeviceInputOuputCG6.cc (13 of 18)

      //  
      //  Lock the DGA window for our use.  
      //  
      DGA_WIN_LOCK(infop);  
  
      //  
      //  We grab the cliplist every time since checking it may have  
      //  cause problems with molecules that go directly to the display  
      //  which need to know if the window has been modified.  It's  
      //  cheap enough.  
      //  
      cliplist = dga_win_clipinfo(infop);  
      dga_win_bbox(infop, &win_x, &win_y, &win_width, &win_height);  
  
      //  
      //  Intersect the ROI list and the window cliplist to generate the  
      //  actual ROI of pixels we will touch on the display.  
      //  
      XilRoi* clipped_roi = roi->intersect(cliplist,  
                                           (int)(win_x+x_origin+offset_x),  
                                           (int)(win_y+y_origin+offset_y));  
      if(clipped_roi == NULL) {  
          XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-7",FALSE);  
          DGA_WIN_UNLOCK(infop);  
          return;  
      }  
  
      //  
      //  Get the ROI as a list of rectangles...  
      //  
      XilRoiList* roi_list = clipped_roi->getRectList();  
      if(roi_list == NULL) {  
          XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-8",FALSE);  
          return;  
      }  
  
      //  
      //  Take into account the child offsets  
      //  
      win_x += offset_x;  
      win_y += offset_y;  

Code Example 3-6 XilDeviceInputOuputCG6.cc (14 of 18)

      //  
      //  Operate over each rectangle.  The rectangles are guaranteed  
      //  not to go out outside of the image.  
      //  
      unsigned int   x_size, y_size;  
      long           x, y;  
      unsigned char* src;  
      unsigned char* dst;  
      while(roi_list->next(&x,&y,&x_size,&y_size)) {  
          //  
          //  All of the rectangles must be adjusted by  
          //    the image origin.  
          //  
          x += x_origin;  
          y += y_origin;  
  
          src = fb_mem +  
              (win_y+y)*fb_width +  
              (win_x+x);  
  
          dst = storage->data +  
              y*storage->scanline_stride +  
              x*storage->pixel_stride;  
  
          //  
          //  If this CG6 supports double loads and stores, then we can  
          //    use xil_memcpy() to put the data onto the screen.  
          //    Otherwise, we must use the plain memcpy() which does not  
          //    accelerate the copy by using double loads and stores.  
          //  
          if(doubleLoadnStore == TRUE) {  
              for(int i=0; i<y_size; i++) {  
                  xil_memcpy(dst, src, x_size);  
  
                  src += fb_width;  
                  dst += storage->scanline_stride;  
              }  
          } else {  
              for(int i=0; i<y_size; i++) {  
                  memcpy(dst, src, x_size);  
  
                  src += fb_width;  

Code Example 3-6 XilDeviceInputOuputCG6.cc (15 of 18)

                  dst += storage->scanline_stride;  
            }  
        }  
     }  
  
      //  
      //  Unlock the DGA window.  
      //  
      DGA_WIN_UNLOCK(infop);  
  
      //  
      //  Destroy all of the ROIs I created.  
      //  
      clipped_roi->destroy();  
      roi_list->destroy();  
  
      //  
      //  Mark the XIL image backing storage as Valid  
      //  
      setMemoryValid(TRUE);  
  }  
  
  void  
  install_cmap(Dga_cmap       dga_cmap,  
               int            index,  
               int            count,  
               Xil_unsigned8* red,  
               Xil_unsigned8* green,  
               Xil_unsigned8* blue)  
  {  
      cg6_cmap* cg6cmap = (cg6_cmap*)dga_cm_get_client_infop(dga_cmap);  
  
      //  
      //  Store colors side-by-side  
      //  
      static Xil_unsigned8 cmap[3*256];  
      for(int i=0,j=0; j<count; i+=3,j++) {  
          cmap[i]   = red[j];  
          cmap[i+1] = green[j];  
          cmap[i+2] = blue[j];  
      }  

Code Example 3-6 XilDeviceInputOuputCG6.cc (16 of 18)

      //  
      //  cg6 Cmap  
      //  
      cg6cmap->addr = index << 24;  
  
      int             nument  = (((count<<1)+count)>>2);  // ncolors*3  
      volatile u_int* hw_cmap = &cg6cmap->cmap;  
      int*            incmap = (int*) cmap;  
      for(i=0; i<nument; i++, incmap++) {  
          *hw_cmap = *incmap;  
          *hw_cmap = *incmap << 8;  
          *hw_cmap = *incmap << 16;  
          *hw_cmap = *incmap << 24;  
      }  
  }  
  
  int  
  XilDeviceInputOutputCG6::setDeviceAttribute(char  attribute_name[],  
                                              void* value)  
  {  
      if(!strcmp(attribute_name, "XCOLORMAP")) {  
       XilColorList*  clist   = (XilColorList*)value;  
  
       if(clist->cmap != xcmap) {  
           if(clist->cmap != 0) {  
       //  
       //  UnGrab Cmap Grabber  
       //  
       XDgaUnGrabColormap(displayptr, xcmap);  
       dga_cmap = NULL;  
           }  
           xcmap = 0;  
  
           //  
           //  Connect to the Cmap Grabber  
           //  
           Dga_token dga_token = XDgaGrabColormap(displayptr, clist->cmap);  
           if(dga_token==NULL) {  
         XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-219",TRUE);  
       return XIL_FAILURE;  
           }  
           if((dga_cmap =  

Code Example 3-6 XilDeviceInputOuputCG6.cc (17 of 18)

                  ((Dga_cmap) dga_cm_grab(dga_win_devfd(infop),  
                                          dga_token))) == NULL) {  
         XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-219",TRUE);  
       XDgaUnGrabColormap(displayptr, clist->cmap);  
       return XIL_FAILURE;  
           }  
           xcmap = clist->cmap;  
  
           //  
           //  Mmap Hardware  
           //  
           if((cg6cmap = (struct cg6_cmap*)  
       mmap(NULL, CG6_CMAP_SZ, PROT_READ|PROT_WRITE,  
            MAP_PRIVATE, fd, CG6_VADDR_CMAP)) ==  
                 (struct cg6_cmap*)-1) {  
         XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-215",TRUE);  
       return XIL_FAILURE;  
           }  
  
              dga_cm_set_client_infop(dga_cmap, cg6cmap);  
       }  
  
       XColor*        colors  = clist->colors;  
       Xil_unsigned32 ncolors = clist->ncolors;  
       unsigned long  index  = colors[0].pixel;  
  
       //  
       // Check to see if the colors are linear and convert  
       //  
       static Xil_unsigned8  red[256], green[256], blue[256];  
       for(int i=(int)(index),j=0; i<(ncolors+index); i++,j++) {  
           if(colors[i-index].pixel != i) {  
       XStoreColors(displayptr, clist->cmap, colors, ncolors);  
       return XIL_SUCCESS;  
           }  
  
           red[j]   = colors[j].red>>8;  
           green[j] = colors[j].green>>8;  
           blue[j]  = colors[j].blue>>8;  
       }  

Code Example 3-6 XilDeviceInputOuputCG6.cc (18 of 18)

       //  
       //  Install the new colormap.  
       //  
          dga_cm_write(dga_cmap, (int)index, ncolors,  
                       red, green, blue, install_cmap);  
  
          return XIL_SUCCESS;  
      }  
  
      return XIL_FAILURE;  
  }  
  
  int XilDeviceInputOutputCG6::getDeviceAttribute(char attribute_name[],  
                                                 void** value)  
  {  
      if (!strcmp(attribute_name,"WINDOW"))  
          *value= (void *)window;  
      else if (!strcmp(attribute_name,"DISPLAY"))  
          *value= (void *)displayptr;  
      else if (!strcmp(attribute_name,"FBC"))  
          *value= (void *)fb_fbc;  
      else if (!strcmp(attribute_name,"DGA_WIN"))  
          *value= (void *)infop;  
      else  
          return XIL_FAILURE;  
  
      return XIL_SUCCESS;  
  }  

Sample I/O Device Handler

The following example shows an I/O handler that treats an X11 window as a I/O device. It contains an implementation of XilDeviceInputOutputTypeXlib and XilDeviceInputOutputXlib, which are classes derived from XilDeviceInputOutputType and XilDeviceInputOutput, respectively. It also shows sample implementations of the member functions of these classes. This is the code delivered in the XIL library to allow device images to be created from X11 windows.
Code Example 3-7 XlibCreateType.cc (1 of 14)

  //This line lets emacs recognize this as -*- C++ -*- Code  
  //------------------------------------------------------------------------  
  //  
  //  Description:  
  //  Contains the member functions of XilDeviceInputOutputTypeXlib  
  //      and XilDeviceInputOutputXlib.  
  //  
  //  
  //  
  //------------------------------------------------------------------------  
  #pragma ident    "@(#)XlibCreateType.cc1.2\t94/03/23  "  
  
  #include <stdlib.h>  
  #include <X11/Xlib.h>  
  #include <X11/Xutil.h>  
  #include <xil/xili.h>  
  
  /*  
   * Derived instantiation of XilDeviceInputOutputType class  
   * This is the description of the connection to the device  
   * There is only one of these  
   */  
  class XilDeviceInputOutputTypeXlib : public XilDeviceInputOutputType {  
    public:  
      virtual XilDeviceInputOutput* createDeviceInputOutput(  
                  XilImage* parent, void* data);  
  };  
  
  /*  
   * Derived instantiation of XilDeviceInputOutput class  

Code Example 3-7 XlibCreateType.cc (2 of 14)

   * This is the description of a particular instantiation of the device  
   * There can be many of these  
   */  
  class XilDeviceInputOutputXlib : public XilDeviceInputOutput {  
    public:  
     virtual int setDeviceAttribute(char attrbute_name[], void* value);  
     virtual int getDeviceAttribute(char attribute_name[], void** value);  
     virtual void display(XilImage*);  
     virtual void capture(XilImage*);  
     virtual void getPixel(unsigned short x, unsigned short y,  
                           unsigned short band, unsigned short count,  
                           float *data);  
     virtual void setPixel(unsigned short x, unsigned short y,  
                           unsigned short band, unsigned short count,  
                           float *data);  
  
      XilDeviceInputOutputXlib(XilImage* parent, void* data);  
      virtual ~XilDeviceInputOutputXlib();  
    private:  
      Display* displayptr;  
      Window window;  
      XImage* xImage;  
      unsigned int x_depth;  
      GC gc;  
  };  
  
  /*  
   * This is the global function called by XIL to create this kind of  
   * I/O device  
   */  
  XilDeviceInputOutputType *XilCreateInputOutputType()  
  {  
      return(new XilDeviceInputOutputTypeXlib());  
  }  
  
  /*  
   * This is the routine that creates new images on this particular I/O  
   * device  
   */  
  XilDeviceInputOutput* XilDeviceInputOutputTypeXlib::createDeviceInputOutput(  
      XilImage* parent, void* data)  
  {  

Code Example 3-7 XlibCreateType.cc (3 of 14)

     XilDeviceInputOutputXlib* device;  
     device=new XilDeviceInputOutputXlib(parent,data);  
     if (device==NULL) {  
        XIL_ERROR(NULL,XIL_ERROR_RESOURCE,"di-1",TRUE);  
        return NULL;  
     }  
     if (device->getImageType()==NULL) {  
        XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-188",FALSE);  
        delete device;  
        return NULL;  
     }  
     return(device);  
  }  
  
  /*  
   * Constructor for an object (image) of this device  
   */  
  XilDeviceInputOutputXlib::XilDeviceInputOutputXlib(  
      XilImage* parent,void* data)  
  {  
     XGCValues gc_val;  
     XilWindow* window;  
     XilDataType depth;  
     unsigned int nbands;  
     unsigned int width;  
     unsigned int height;  
  
     window = (XilWindow*)data;  
  
     /* indicate readability and writeability */  
     readable= TRUE;  
     writeable= TRUE;  
  
     /* save the display and window */  
     this->displayptr= window->display;  
     this->window= window->window;  
  
     /* find out the image type */  
     {  
        Window root;  
        int x,y;  
        unsigned int border_width;  

Code Example 3-7 XlibCreateType.cc (4 of 14)

        Status status=XGetGeometry(displayptr,this->window,&root,&x,&y,&width,  
                                   &height,&border_width, &x_depth);  
        if (status==0) {  
           XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-220",TRUE);  
           imageType=NULL;  
           return;  
        }  
     }  
     switch (x_depth) {  
      case 1:  
         depth= XIL_BIT;  
         nbands= 1;  
         imageType=realImageType=  
            parent->getSystemState()->createImageType(width,height,1,depth);  
         break;  
      case 4:  
      case 8:  
         depth= XIL_BYTE;  
         nbands= 1;  
         imageType=realImageType=  
            parent->getSystemState()->createImageType(width,height,1,depth);  
         break;  
      case 16:  
         depth= XIL_SHORT;  
         nbands= 1;  
         imageType=realImageType=  
            parent->getSystemState()->createImageType(width,height,1,depth);  
         break;  
      case 24:  
         depth= XIL_BYTE;  
         nbands= 3;  
         imageType=parent->getSystemState()-  
  >createImageType(width,height,3,depth);  
         realImageType=parent->getSystemState()-  
  >createImageType(width,height,4,depth);  
         break;  
      default:  
         imageType=realImageType=NULL;  
         break;  
     }  
     if (imageType==NULL) {  
        XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-188",FALSE);  

Code Example 3-7 XlibCreateType.cc (5 of 14)

        return;  
     }  
     if (realImageType==NULL) {  
        XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-188",FALSE);  
        imageType->destroy();  
        imageType=NULL;  
        return;  
     }  
  
     /* create a graphics context */  
     gc_val.foreground= 0;  
     gc_val.function= GXcopy;  
     this->gc= XCreateGC(displayptr,this-  
  >window,GCForeground|GCFunction,&gc_val);  
     if (!this->gc) {  
        XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-162",TRUE);  
        imageType->destroy();  
        imageType=NULL;  
        return;  
     }  
  
     /* create an X image */  
     XWindowAttributes win_attr;  
     if (!XGetWindowAttributes(displayptr,this->window,&win_attr)) {  
        XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-249",TRUE);  
        XFreeGC(displayptr,gc);  
        imageType->destroy();  
        imageType=NULL;  
        return;  
     }  
     xImage=  
  XCreateImage(displayptr,win_attr.visual,win_attr.depth,ZPixmap,0,0,  
                       10, 10, 8, 0);  
     if (xImage==NULL) {  
        XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-250",TRUE);  
        XFreeGC(displayptr,gc);  
        imageType->destroy();  
        imageType=NULL;  
        return;  
     }  

Code Example 3-7 XlibCreateType.cc (6 of 14)

     /* go ahead and throw way the storage that the X image created  
      * since we'll be copying directly out of the XIL image  
      */  
     XFree(xImage->data);  
     xImage->data=NULL;  
  
     /* get the display operation numbers */  
     displayOpNumber=XilLookupOpNumber("display_ioxlib");  
     captureOpNumber=XilLookupOpNumber("capture_ioxlib");  
  }  
  
  /*  
   * This is the destructor for the storage device  
   */  
  XilDeviceInputOutputXlib::~XilDeviceInputOutputXlib()  
  {  
     if (imageType) {  
        XFreeGC(displayptr,gc);  
        xImage->data=NULL;  
        XDestroyImage(xImage);  
        imageType->destroy();  
        if (realImageType!=imageType) realImageType->destroy();  
     }  
  }  
  
  /*  
   * write image to device  
   */  
  void XilDeviceInputOutputXlib::display(XilImage* copy_image)  
  {  
     unsigned short width,height,nbands;  
     XilDataType data_type;  
     XilMemoryStorage* storage;  
     long x_origin, y_origin;  
     XilRoi* roi;  
     XilRoiList* roi_list;  
     long x,y;  
     unsigned int offset_x,offset_y,offset_band;  
  
     /* get information about the image */  
     copy_image->getInfo(&width,&height,&nbands,&data_type);  
     copy_image->getOrigin(&x_origin,&y_origin);  

Code Example 3-7 XlibCreateType.cc (7 of 14)

     /* get format information and put it into the X image*/  
     storage= (XilMemoryStorage*)copy_image->getMemoryStorage();  
     if (storage==NULL) {  
        XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-140",FALSE);  
        return;  
     }  
  
     /* get the child offset information */  
     copy_image->getChildOffsets(&offset_x,&offset_y,&offset_band);  
  
     switch (copy_image->getDataType()) {  
      case XIL_BIT:  
        xImage->data= (char*)storage->bit.data;  
        xImage->bytes_per_line= (int)storage->bit.scanline_stride;  
        break;  
      case XIL_BYTE:  
        xImage->data= (char*)storage->byte.data-offset_band;  
        xImage->bytes_per_line= (int)storage->byte.scanline_stride;  
        break;  
      case XIL_SHORT:  
        xImage->data= (char*)storage->shrt.data;  
        xImage->bytes_per_line= (int)storage->shrt.scanline_stride*2;  
        break;  
      case XIL_FLOAT:  
        XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-216",FALSE);  
        return;  
     }  
     xImage->width= width;  
     xImage->height= height;  
  
     /* figure out the plane mask */  
     if (x_depth==24) {  
        unsigned long mask;  
        switch (copy_image->getBands()) {  
         case 1:  
           mask= 0xFF0000;  
           break;  
         case 2:  
           mask= 0xFFFF00;  
           break;  
         case 3:  
           mask= 0xFFFFFF;  

Code Example 3-7 XlibCreateType.cc (8 of 14)

           break;  
        }  
        mask= mask >> ((offset_band-1) * 8);  
        XSetPlaneMask(displayptr,gc,mask);  
     }  
  
     /* get ROI */  
     roi= copy_image->getPixelsTouchedRoi();  
     if (roi==NULL) {  
        XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-6",FALSE);  
        return;  
     }  
  
     /* get the roi list from the roi */  
     roi_list= roi->getRectList();  
     if (roi_list==NULL) {  
        XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-8",FALSE);  
        return;  
     }  
  
     /* operate on each ROI, all of the regions are guaranteed not to go outside  
      * the image  
      */  
     unsigned int x_size,y_size;  
     while (roi_list->next(&x,&y,&x_size,&y_size)) {  
        x+= x_origin;  
        y+= y_origin;  
        XPutImage(displayptr,window,gc,xImage,(int)x,(int)y,(int)x+offset_x,  
                  (int)y+offset_y,x_size,y_size);  
     }  
  
     /* se the plane mask back to normal */  
     if (x_depth==24) XSetPlaneMask(displayptr,gc,0xFFFFFF);  
  
     XFlush(displayptr);  
     xImage->data= NULL;  
     roi_list->destroy();  
  }  

Code Example 3-7 XlibCreateType.cc (9 of 14)

  /*  
   * read image from device  
   */  
  void XilDeviceInputOutputXlib::capture(XilImage* copy_image)  
  {  
     unsigned short width,height,nbands;  
     XilDataType data_type;  
     XilMemoryStorage* storage;  
     long x_origin, y_origin;  
     XilRoi* roi;  
     XilRoiList* roi_list;  
     long x,y;  
     unsigned int offset_x,offset_y,offset_band;  
  
     /* get information about the image */  
     copy_image->getInfo(&width,&height,&nbands,&data_type);  
     copy_image->getOrigin(&x_origin,&y_origin);  
  
     /* get format information and put it into the X image*/  
     storage= (XilMemoryStorage*)copy_image->getMemoryStorage();  
     if (storage==NULL) {  
        XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-140",FALSE);  
        return;  
     }  
  
     /* get the child offset information */  
     copy_image->getChildOffsets(&offset_x,&offset_y,&offset_band);  
  
     switch (copy_image->getDataType()) {  
      case XIL_BIT:  
        xImage->data= (char*)storage->bit.data;  
        xImage->bytes_per_line= (int)storage->bit.scanline_stride;  
        break;  
      case XIL_BYTE:  
        xImage->data= (char*)storage->byte.data-offset_band;  
        xImage->bytes_per_line= (int)storage->byte.scanline_stride;  
        break;  
      case XIL_SHORT:  
        xImage->data= (char*)storage->shrt.data;  
        xImage->bytes_per_line= (int)storage->shrt.scanline_stride*2;  
        break;  
      case XIL_FLOAT:  

Code Example 3-7 XlibCreateType.cc (10 of 14)

        XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-216",FALSE);  
        return;  
     }  
     xImage->width= width;  
     xImage->height= height;  
  
     /* get ROI */  
     roi= copy_image->getImageSpaceRoi();  
     if (roi==NULL) {  
        XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-6",FALSE);  
        return;  
     }  
  
     /* get the roi list from the roi */  
     roi_list= roi->getRectList();  
     if (roi_list==NULL) {  
        XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-8",FALSE);  
        return;  
     }  
  
     /* operate on each ROI, all of the regions are guaranteed not to go outside  
      * the image  
      */  
     unsigned int x_size,y_size;  
     while (roi_list->next(&x,&y,&x_size,&y_size)) {  
        x+= x_origin;  
        y+= y_origin;  
        XGetSubImage(displayptr,window,(int)x+offset_x,(int)y+offset_y,  
                     x_size,y_size,0xffffffff,ZPixmap,xImage,(int)x,(int)y);  
     }  
     XFlush(displayptr);  
     xImage->data= NULL;  
     roi_list->destroy();  
  }  
  
  void XilDeviceInputOutputXlib::setPixel(unsigned short x, unsigned short y,  
                                   unsigned short band, unsigned short count,  
                                   float* data)  
  {  
     float value;  
     unsigned long pixel;  
     unsigned long mask;  

Code Example 3-7 XlibCreateType.cc (11 of 14)

     /* set the pixel */  
     switch (x_depth) {  
      case 1:  
        value= data[0]+.5;  
        if (value > 1.0) {  
           pixel=1;  
        } else if (value < 0.0) {  
           pixel=0;  
        } else {  
           pixel=(unsigned long)value;  
        }  
        mask=1;  
        break;  
      case 4:  
      case 8:  
        value= data[0]+.5;  
        if (value > 255.0) {  
           pixel=255;  
        } else if (value < 0.0) {  
           pixel=0;  
        } else {  
           pixel=(unsigned long)value;  
        }  
        mask=0xFF;  
        break;  
      case 24:  
        pixel=0;  
        switch (count) {  
         case 3:  
           value= data[2];  
           if (value > 255.0) {  
              pixel|=0xFF0000;  
           } else if (value < 0.0) {  
           } else {  
              pixel |= (unsigned long)value << 16;  
           }  
         case 2:  
           value= data[1];  
           if (value > 255.0) {  
              pixel|=0xFF00;  
           } else if (value < 0.0) {  
           } else {  

Code Example 3-7 XlibCreateType.cc (12 of 14)

              pixel |= (unsigned long)value << 8;  
           }  
         case 1:  
           value= data[0];  
           if (value > 255.0) {  
              pixel|=0xFF;  
           } else if (value < 0.0) {  
           } else {  
              pixel |= (unsigned long)value;  
           }  
        }  
        switch (count) {  
         case 1:  
           mask= 0xFF;  
           break;  
         case 2:  
           mask= 0xFFFF;  
           break;  
         case 3:  
           mask= 0xFFFFFF;  
           break;  
        }  
        mask = mask << (band * 8);  
        pixel = pixel << (band * 8);  
     }  
     XSetPlaneMask(displayptr,gc,mask);  
     XSetForeground(displayptr,gc,pixel);  
     XDrawPoint(displayptr,window,gc,x,y);  
     XSetPlaneMask(displayptr,gc,0xffffffff);  
     XFlush(displayptr);  
  }  
  
  void XilDeviceInputOutputXlib::getPixel(unsigned short x, unsigned short y,  
                                   unsigned short band, unsigned short count,  
                                   float* data)  
  {  
     unsigned long pixel;  
     XImage* image;  
  
     image=XGetImage(displayptr,window,x,y,1,1,0xFFFFFF,ZPixmap);  
     if (!image) {  
        XIL_ERROR(NULL,XIL_ERROR_SYSTEM,"di-316",TRUE);  

Code Example 3-7 XlibCreateType.cc (13 of 14)

        return;  
     }  
     pixel= XGetPixel(image,0,0);  
     XDestroyImage(image);  
  
     switch (x_depth) {  
      case 1:  
      case 4:  
      case 8:  
        data[0]=pixel;  
        break;  
      case 24:  
        pixel >> (band * 8);  
        switch (count) {  
         case 3:  
           data[2]= (pixel & 0xFF) >> 16;  
           /* break intentionally omitted */  
         case 2:  
           data[1]= (pixel & 0xFF) >> 8;  
           /* break intentionally omitted */  
         case 1:  
           data[0]= pixel & 0xFF;  
           /* break intentionally omitted */  
        }  
        break;  
     }  
  }  
  
  int XilDeviceInputOutputXlib::setDeviceAttribute(char attribute_name[],  
                                                    void* value)  
  {  
      if (!strcmp(attribute_name,"XCOLORMAP")) {  
       XilColorList* clist = (XilColorList*)value;  
       XStoreColors(displayptr, clist->cmap, clist->colors, clist->ncolors);  
          return XIL_SUCCESS;  
      }  
      return XIL_FAILURE;  
  }  
  
  int XilDeviceInputOutputXlib::getDeviceAttribute(char attribute_name[],  
                                                   void **value)  

Code Example 3-7 XlibCreateType.cc (14 of 14)

  {  
    if (!strcmp(attribute_name,"WINDOW"))  
      *value=(void *)window;  
    else if (!strcmp(attribute_name,"DISPLAY"))  
      *value=(void *)displayptr;  
    else  
      return XIL_FAILURE;  
  
    return XIL_SUCCESS;  
  }