XIL Device Porting and Extensibility Guide
只搜尋這本書
以 PDF 格式下載這本書

Storage Devices

5

About Storage Devices

Storage device handlers allow images to reside in places besides host CPU memory or in a format different from the standard memory layout. They are always associated with a compute device, allowing an accelerator to take advantage of image data remaining local to the accelerator during sequential function calls. Since accelerators usually have their own idea of how image data memory is laid out, storage handlers allow reformatting of data as it is copied between devices.
The handlers for storage devices are responsible for allocating, deallocating, and describing the data format of the storage on their device. A particular function from a compute device will request the image in a specific storage type (format) via a call to the getStorage() member of the XilImage class. The storage handler attempts to satisfy that request and return a description of the image's data layout in the requested format. There is a close relationship between a compute device and the associated storage device.
In addition to the above functions, it is useful to have the storage handler perform single-pixel access for xil_get_pixel() and xil_set_pixel() to avoid having to copy all of the image data in that case.
A storage device is not required to be able to handle all images, but can limit the sort of images it will store based on any parameter. For example, a storage device may only be capable of storing 8-bit images, or images that are 320-by-240 pixels in size. Processing functions that request this restricted
storage must either know of these restrictions and use alternate storage devices for noncompliant images, or correctly handle the failure of a storage request by attempting alternative storage.
Aside from storing data, the main job of a storage handler is format conversion. The interface provided via getStorage() is an attempt at a compromise between forcing every device to convert to a single interchange format and requiring each handler to convert between every possible format. The former forces an intermediate copy between devices, while the latter is actually impossible, since the potential list of device formats is unlimited.
Much like I/O devices, storage devices are loaded the first time they are needed. Typically, a compute device handler will cause the storage device handler for a device to be loaded when it first tries to create an image of the associated storage type. The CPU memory storage handler is loaded at the time of the first image creation.
Each storage handler must contain the following global function:
XilDeviceStorageType* XilCreateStorageType()

This function is called by the handler loader and performs device initialization and sets up any data that will be used by all instances of the storage device.

XilDeviceStorageType Class

This class describes the connection to a storage device. There is only one instance of this class for each type of storage device, which is created by the device-specific driver. In addition to implementing this class, the driver can add any device-dependent data or functions that are not needed in every instance of a storage handler.
XilDeviceStorageType is the abstract class shown below:
Code Example 5-1 Definition of XilDeviceStorageType Class

  class XilDeviceStorageType : public XilDeviceType {  
   public:  
   //  
   // This is the propagate-to-this-device call.  
   //  
   // This is the function that creates new images on this particular device,  

Code Example 5-1 Definition of XilDeviceStorageType Class

   // or moves images from memory to this device. The 'typename' field  
   // tells the name of the storage type that the 'image' is currently.  
   // If this storage device knows about the internals of the device type  
   // specified by 'typename', then it creates a new storage device of  
   // this type, copies the image data into it, and returns pointers to  
   // both the new storage device and the device dependent 'description'  
   // of the storage. Otherwise it should return NULL. All storage devices  
   // need to know how to propagate from memory. The 'take_ownership'  
   // field tells the device driver whether it should delete the data  
   // when the storage object is destroyed. See the example storage driver  
   // for more information.  
   //  
   virtual XilDeviceStorage * propagateDeviceStorage (XilImage *image,  
           char typename[], void *description,  
           int take_ownership)=0;  
  
   // destructor. This should release all resources that were used to  
   // make the connection to the device.  
  
   virtual ~XilDeviceStorageType();  
  };  

The handler creates a device-specific class that derives from XilDeviceStorageType. All device-specific information unique to this instance of the object should be stored here. In the storage handler example on page 154, this class is used to derive a storage handler that supports band-sequential data. The class XilDeviceStorageTypeBandMemory is derived from XilDeviceStorageType.
propagateDeviceStorage() in the type class implements image data transfer to the device. If the handler knows how to read image storage from the device typename, it must create the image storage, copy the image data from the named device, and return a pointer to the local image storage. If take_ownership is true, the device storage handler should delete the image data storage when the image is destroyed. If the handler does not know how to propagate from the specified device, it should return NULL.
All device storage handlers must know how to propagate to and from the memory device, and may know about other devices as well. When a propagation is requested, the core code first tries to use the source and
destination devices to see if either knows how to copy directly between the two devices. If neither knows how to copy directly, then two propagations are used: one from the source device to standard memory and a second from standard memory to the destination device.
The propagateDeviceStorage() function returns derived instances of the storage object for a particular device.

XilDeviceStorage Class

This class describes one instance of a particular storage device. Many of these can exist.
The abstract class for XilDeviceStorage looks like this:
Code Example 5-2 Definition of XilDeviceStorage Class

  //------------------------------------------------------------------------  
  //  
  // Description:  
  //  
  //  Definition of the interface to the XilDeviceStorage class  
  //  
  //------------------------------------------------------------------------  
  
  class XilDeviceStorage : public XilDevice {  
   public:  
   //  
   // This function allows this device to emulate other device types, so  
   // that images can be shared across devices that know about each other  
   // without needing to copy the data. It returns a pointer to the  
   // device dependent structure that describes the internal information  
   // about how to access the image as if it were the specified type.  
   // The image should either be of the specified type or the storage device  
   // driver should be capable of efficiently emulating the specified type.  
   // If the storage device cannot emulate the requested type than this  
   // function should return NULL.  
   //  
   virtual void* requestStorageInfo (char typename[])=0;  
   //  
   // This is the propagate-from-this-device call.  
   //  
   // This is the function that moves images from the current device to  

Code Example 5-2 Definition of XilDeviceStorage Class (Continued)

   // the named device. If this storage device knows about the internals  
   // of the device type specified by 'typename', then it creates a new  
   // storage device of the requested type, copies the image data into it,  
   // and returns a pointer to it. If the storage device cannot convert  
   // directly to the requested type then it should return NULL.  
   //  
   // All storage devices need to know how to convert to a 'memory' type image.  
   //  
   virtual XilDeviceStorage* propagateDeviceStorage (char typename[])=0;  
  
   //  
   // functions to get and set particular image pixel values without  
   // forcing a propagation of the image to memory  
   //  
   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;  
  
   //  
   // destructor. This should release all resources that were used to  
   // make this particular storage device.  
   //  
   virtual ~XilDeviceStorage();  
  };  

The device storage driver should create a device-specific class derived from XilDeviceStorage. The instance of this derived class represents the storage of data for a single image.
requestStorageInfo() should return a device-dependent structure that describes the memory layout for the specific image data storage as if it were the specified type. If the image is not of the specified type, or cannot be efficiently treated as if it is of the specified type, requestStorageInfo() should return NULL. This additional complexity allows an image that resides on a device that can be memory-mapped to expose the device-resident image as a memory image.
The device-dependent storage information need not include things like the image width and height, since that information is available in the device-independent image class.
propagateDeviceStorage() in the device class copies data from the current device into the named device. If the handler knows about the device type specified by typename, it should create a new storage device of the requested type, copy the data into it, and return a pointer to the new storage class. As mentioned above, it should return NULL if it cannot convert the data to the requested storage type, but it must be capable of converting to the memory storage type.
getPixel() and setPixel() are used to implement the corresponding API-level functions. They are part of the storage class to prevent having to propagate the image in order to return single pixel values. The pixel information these functions return is an array of floating point data with a size equal to the number of bands in the image.
One note of caution concerning the getStorage() member of XilImage: it does not respect the existence of children. This means that if getStorage() is called on a spatial or band child, getStorage() returns the storage information for the parent image, not the child. Since the caller usually wants the information corresponding to the child image, getStorage() is not usually called directly, but rather through a utility function. In the storage handler example on page 154, this utility function is called getBandMemoryStorage(). It calls getStorage("band_memory"), which returns the parent data. It then constructs the appropriate data structure for the requested child image.

Adding a Storage Device

The decision to implement a storage handler should be driven by the performance enhancement expected from allowing the image data to reside on an accelerator. If an accelerator performs several atomic operations that are likely to be called in sequence, it will undoubtedly be advantageous to provide a storage handler to support the compute handler for the accelerator. If, however, the accelerator only provides functionality for a single operator (for example, a JPEG decompressor), the advantage of keeping the image data local to the accelerator is minimal, since the next usage of the image would cause the propagation to the memory format anyway. Storage handlers also can be used to allow local data on an I/O device, but, in the same way, it is of little advantage if the I/O device cannot perform subsequent operators.
Storage devices that modify the format of the image without tying it to an actual hardware device can be useful as well. (The storage handler example on page 154 is this sort of storage device). However, before such a storage handler can be used, there must exist compute handlers that ask for this storage format.
Adding a storage device is relatively simple compared to compute or compression devices. The handler writer must perform the following steps:
  1. Subclass the XilDeviceStorageType class to represent the desired storage type. If there is initialization needed for the storage device, it should go here. The propagateDeviceStorage() defined here should create instances of the class derived below, from XilDeviceStorage. If take_ownership is TRUE, the data associated with the image should be deallocated when the XilDeviceStorage instance's destructor is called.

  2. Subclass the XilDeviceStorage class to represent the desired storage. As a minimum, the implementation of propagateDeviceStorage() from the derived XilDeviceStorage class must be able to propagate the image data to and from the memory storage format. The internal representation of the XIL memory layout is pixel interleaved (except for bit images), exactly the same as exported data. This exported format is described in the XIL Reference Manual under xil_get_memory_storage(). If the writer of the handler has in-depth knowledge of the layout of some other storage format, the function may also allow propagation to and from that additional format.

  3. The implementation should be placed in the file $XILHOME/lib/pipelines/xildevice_name.so, where device_name is the name of the storage device (see the section on handler installation in

Chapter 2, "More on Writing Device Handlers"). Storage devices are not referenced as dependencies in the xil.compute configuration file, but are referenced directly by name via the getStorage() parameters.

Sample Storage Device Handler

This example illustrates a storage handler for memory images that are stored in band-sequential format. (The standard XIL memory operators expect images stored in a pixel-sequential format). The example is fairly complete, and illustrates the majority of the features of a storage driver. Note, however, that this example only works for 1-band images (of any type), or XIL_BIT images (XIL already stores them in band-sequential format). For the handler to be fully functional, the copyMemory2BandMemory() and copyBandMemory2Memory() routines would need to be implemented. This example contains two files:
  • XilBandMemoryDefines.h, which describes structures needed by the storage handler
  • XilDeviceStorageTypeBandMemory.cc, which implements the storage handler

XilBandMemoryDefines.h

Code Example 5-3 XilBandMemoryDefines.h

  #ifndef XIL_BANDMEMORYDEFINES_H  
  #define XIL_BANDMEMORYDEFINES_H  
  
  //  
  // Definition of band-sequential memory storage description  
  // Other storage drivers may need other information as well (file descriptors,  
  // accelerator ids, etc.)  
  //  
  
  typedef struct __XilBandMemoryStorageBit {  
     Xil_unsigned8* data;            /* pointer to the first byte of the image */  
     unsigned short scanline_stride; /* the number of bytes between scanlines */  
     unsigned long band_stride;      /* the number of bytes between bands */  
     unsigned char offset;           /* the number of bits to the first pixel */  
  } XilBandMemoryStorageBit;  
  
  typedef struct __XilBandMemoryStorageByte {  
     Xil_unsigned8* data;            /* pointer to the first byte of the image */  
     unsigned long scanline_stride;  /* the number of bytes between scanlines */  
     unsigned long band_stride;      /* the number of bytes between bands */  
  } XilBandMemoryStorageByte;  
  
  typedef struct __XilBandMemoryStorageShort {  
     Xil_signed16* data;             /* pointer to the first word of the image */  
     unsigned long scanline_stride;  /* the number of shorts between scanlines */  
     unsigned long band_stride;      /* the number of shorts between bands */  
  } XilBandMemoryStorageShort;  
  
  typedef struct __XilBandMemoryStorageFloat {  
     float* data;                    /* pointer to the first float in the image */  
     unsigned long scanline_stride;  /* the number of floats between scanlines */  
     unsigned long band_stride;      /* the number of floats between bands */  
  } XilBandMemoryStorageFloat;  
  
  typedef union __XilBandMemoryStorage {  
     XilBandMemoryStorageBit   bit;  
     XilBandMemoryStorageByte  byte;  
     XilBandMemoryStorageShort shrt;  
     XilBandMemoryStorageFloat flt;  
  } XilBandMemoryStorage;  

Code Example 5-3 XilBandMemoryDefines.h (Continued)

  #endif  


XilDeviceStorageTypeBandMemory.cc

Code Example 5-4 XilDeviceStorageTypeBandMemory.cc (1 of 17)

  #include <strings.h>  
  #include <xil/XilDeviceStorage.h>  
  #include <xil/XilImage.h>  
  #include <xil/XilDeviceStorageType.h>  
  #include <xil/XilError.h>  
  
  #include "XilBandMemoryDefines.h"  
  
  //-------------------------------------------------------------------------  
  //  
  // This is an implementation of a band-sequential (or band-interleaved)  
  // memory storage driver.  The example is fairly complete, and illustrates  
  // the majority of the features of a storage driver.  Note however that  
  // this example only works for 1-band images (of any type), or XIL_BIT  
  // images (since they are already stored in band-sequential format).  In  
  // order to become fully functional, the copyMemory2BandMemory() and  
  // copyBandMemory2Memory() routines would need to be implemented.  
  //  
  //-------------------------------------------------------------------------  
  
  //  
  // Derived instantiation of XilDeviceStorageType class  
  // This is the description of the connection to the device  
  // There is only one of these  
  //  
  class XilDeviceStorageTypeBandMemory : public XilDeviceStorageType {  

Code Example 5-4 XilDeviceStorageTypeBandMemory.cc (2 of 17)

   public:  
     virtual XilDeviceStorage* propagateDeviceStorage(XilImage* image,  
                char type_name[], void* description, int take_ownership);  
   private:  
     XilDeviceStorageTypeBandMemory();  
     ~XilDeviceStorageTypeBandMemory();  
     XilBandMemoryStorage* allocateStorage(XilImage* image);  
     XilBandMemoryStorage* convertMemoryStorage(XilImage* image,  
                      XilMemoryStorage* memory_storage,  
                      Xil_boolean* need_copy);  
  
     // this is a friend for the purpose of calling the constructor  
     friend XilDeviceStorageType* XilCreateStorageType();  
  };  
  
  //  
  // Derived instantiation of XilDeviceStorage class  
  // This is the description of a particular instantiation of the device  
  // There can be many of these  
  //  
  class XilDeviceStorageBandMemory : public XilDeviceStorage {  
   public:  
     virtual void* requestStorageInfo(char typename[]);  
     virtual XilDeviceStorage* propagateDeviceStorage(char typename[]);  
     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);  
   private:  
     XilDeviceStorageBandMemory(XilImage* image, XilBandMemoryStorage*  
  description, int take_ownership);  
     ~XilDeviceStorageBandMemory();  
     XilDataType dataType;// datatype of image  
     XilBandMemoryStorage storage;// device storage description  
     XilMemoryStorage memory_storage;// used for emulating memory images  
     int owner;// whether device owns data or not  
     XilImage* parent;// pointer to parent image description  
     friend class XilDeviceStorageTypeBandMemory;  
  };  

Code Example 5-4 XilDeviceStorageTypeBandMemory.cc (3 of 17)

  //  
  // prototypes of device utility functions (not implemented in this example)  
  //  
  void  
  copyMemory2BandMemory(XilMemoryStorage *, XilBandMemoryStorage *, XilImage *);  
  
  void  
  copyBandMemory2Memory(XilBandMemoryStorage *, XilMemoryStorage *, XilImage *);  
  
  
  //  
  // This is the global function called by XIL to create this kind of storage  
  device  
  //  
  XilDeviceStorageType* XilCreateStorageType()  
  {  
     XilDeviceStorageType* device_type;  
  
     // create the storage type  
     device_type=new XilDeviceStorageTypeBandMemory();  
     if (device_type==NULL) {  
        return NULL;  
     }  
     return device_type;  
  }  
  
  //  
  // This is the constructor for the storage device  
  // It is called only once at startup  
  //  
  XilDeviceStorageTypeBandMemory::XilDeviceStorageTypeBandMemory()  
  {  
     // there is no data to initialize at the moment  
  }  
  
  //  
  // This is the destructor for the storage device  
  // It is called only once at shutdown  
  //  
  XilDeviceStorageTypeBandMemory::~XilDeviceStorageTypeBandMemory()  
  {  

Code Example 5-4 XilDeviceStorageTypeBandMemory.cc (4 of 17)

  }  
  
  //  
  // Routine that creates new images on this particular device, or moves images  
  // from memory to this device.  This is the propagate-to-this-device call.  
  //  
  XilDeviceStorage* XilDeviceStorageTypeBandMemory::propagateDeviceStorage(  
     XilImage* image, char *type_name, void* description, int take_ownership)  
  {  
     // if an image is not being passed in, allocate one  
     if (type_name==NULL) {  
        type_name="band_memory";  
        description= (void*) allocateStorage(image);  
        if (description==NULL) {  
           return NULL;  
        }  
     }  
     else if (strcmp(type_name,"memory")==NULL){  
            // This is a memory image -- we can convert it  
            Xil_boolean need_copy;  
            XilBandMemoryStorage* band_description= (XilBandMemoryStorage *)  
                convertMemoryStorage(image, (XilMemoryStorage*) description,  
  &need_copy);  
            if (band_description==NULL) {  
                // Could not allocate the storage for the converted image  
                return NULL;  
            }  
  
            if(need_copy == TRUE) {  
                // Could not convert the image in place - need to copy it  
                copyMemory2BandMemory((XilMemoryStorage *)description,  
                    band_description,  
                    image);  
             // however, since this is not implemented, clean up and fail  
             delete band_description;  
             return NULL;  
            }  
         else {  
                /* Didn't require copy */  
            }  
            description= band_description;  

Code Example 5-4 XilDeviceStorageTypeBandMemory.cc (5 of 17)

     }  
     else if (strcmp(type_name,"band_memory")) {  
            // This is already a band_memory image -- don't need to do anything  
     }  
     else {  
        // This is an image of a type that this handler cannot interpret -- fail  
        return NULL;  
     }  
  
     // create the storage object  
     XilDeviceStorage* device= new XilDeviceStorageBandMemory(image,  
                    (XilBandMemoryStorage*)description,  
                     take_ownership);  
     if (device==NULL) {  
        if(take_ownership)  
        delete ((XilBandMemoryStorage*)description)->bit.data;  
        delete description;  
        return NULL;  
     }  
  
     // Now that the image is on this device, delete the external reference to it  
     delete description;  
  
     return device;  
  }  
  
  //  
  // Routine that actually allocates the storage on this device  
  //  
  XilBandMemoryStorage*  
  XilDeviceStorageTypeBandMemory::allocateStorage(XilImage* image)  
  {  
     unsigned short width,height,nbands;  
     XilDataType datatype;  
     unsigned long size;  
  
     // allocate the storage description  
     XilBandMemoryStorage* storage= new XilBandMemoryStorage;  
     if (storage==NULL) {  
        return NULL;  
     }  

Code Example 5-4 XilDeviceStorageTypeBandMemory.cc (6 of 17)

     // fill it in  
     image->getInfo(&width,&height,&nbands,&datatype);  
     switch (datatype) {  
      case XIL_BIT:  
         storage->bit.scanline_stride=(unsigned short)(width+XIL_BIT_ALIGNMENT-  
  1)/  
           XIL_BIT_ALIGNMENT*(XIL_BIT_ALIGNMENT/8);  
         storage->bit.band_stride=storage->bit.scanline_stride*height;  
         storage->bit.offset= 0;  
         size= storage->bit.band_stride*nbands;  
         break;  
      case XIL_BYTE:  
         storage->byte.scanline_stride= width*nbands;  
         storage->byte.band_stride=storage->byte.scanline_stride*height;  
         size= width*height*nbands*sizeof(Xil_unsigned8);  
         break;  
      case XIL_SHORT:  
         storage->shrt.scanline_stride= width*nbands;  
         storage->shrt.band_stride=storage->shrt.scanline_stride*height;  
         size= width*height*nbands*sizeof(Xil_signed16);  
         break;  
      case XIL_FLOAT:  
         storage->flt.scanline_stride= width*nbands;  
         storage->flt.band_stride=storage->flt.scanline_stride*height;  
         size= width*height*nbands*sizeof(float);  
         break;  
      default:  
         return NULL;  
     }  
  
     // allocate the actual storage  
     storage->bit.data= new Xil_unsigned8[size];  
     if (storage->bit.data==NULL) {  
        delete storage;  
        return NULL;  
     }  
  
     return storage;  
  }  

Code Example 5-4 XilDeviceStorageTypeBandMemory.cc (7 of 17)

  //  
  // Constructor for an object (image) of this device  
  //  
  XilDeviceStorageBandMemory::XilDeviceStorageBandMemory(  
     XilImage* image,  
     XilBandMemoryStorage* storage,  
     int take_ownership)  
  {  
     // copy the description  
     dataType= image->getDataType();  
     switch (dataType) {  
      case XIL_BIT:  
        this->storage.bit= storage->bit;  
        break;  
      case XIL_BYTE:  
        this->storage.byte= storage->byte;  
        break;  
      case XIL_SHORT:  
        this->storage.shrt= storage->shrt;  
        break;  
      case XIL_FLOAT:  
        this->storage.flt= storage->flt;  
        break;  
     }  
  
     owner=take_ownership;  
     parent= image;  
  }  
  
  //  
  // Destructor for an object (image) of this device  
  //  
  XilDeviceStorageBandMemory::~XilDeviceStorageBandMemory()  
  {  
     // throw away the data if owner  
     if (owner) {  
        switch (dataType) {  
         case XIL_BIT:  
           delete storage.bit.data;  
           break;  
         case XIL_BYTE:  
           delete storage.byte.data;  

Code Example 5-4 XilDeviceStorageTypeBandMemory.cc (8 of 17)

           break;  
         case XIL_SHORT:  
           delete storage.shrt.data;  
           break;  
         case XIL_FLOAT:  
           delete storage.flt.data;  
           break;  
        }  
     }  
  }  
  
  //  
  // Routine that allows this device to emulate other device types, so  
  // images can be shared across devices that know about each other without  
  // needing to copy them  
  //  
  void* XilDeviceStorageBandMemory::requestStorageInfo(char typename[])  
  {  
     if (strcmp(typename,"band_memory")==NULL) {  
        // image is of requested type, don't need to do anything  
        return &storage;  
     }  
     else if ((strcmp(typename,"memory")==NULL) &&  
        ((parent->getBands() == 1) || (dataType == XIL_BIT))) {  
        // 1-banded band_memory images have the same storage representation as  
        // memory images.  Also, 1-bit memory images are already band-sequential.  
        // In either of these cases, we can emulate a memory image by passing back  
        // the appropriate storage description.  
        switch (dataType) {  
         case XIL_BIT:  
            memory_storage.bit.scanline_stride= storage.bit.scanline_stride;  
            memory_storage.bit.band_stride= storage.bit.band_stride;  
            memory_storage.bit.offset= storage.bit.offset;  
            memory_storage.bit.data= storage.bit.data;  
            break;  
         case XIL_BYTE:  
            memory_storage.byte.scanline_stride= storage.byte.scanline_stride;  
            memory_storage.byte.pixel_stride= 1;  
            memory_storage.byte.data= storage.byte.data;  
            break;  

Code Example 5-4 XilDeviceStorageTypeBandMemory.cc (9 of 17)

         case XIL_SHORT:  
            memory_storage.shrt.scanline_stride= storage.shrt.scanline_stride;  
            memory_storage.shrt.pixel_stride= 1;  
            memory_storage.shrt.data= storage.shrt.data;  
            break;  
         case XIL_FLOAT:  
            memory_storage.flt.scanline_stride= storage.flt.scanline_stride;  
            memory_storage.flt.pixel_stride= 1;  
            memory_storage.flt.data= storage.flt.data;  
            break;  
         default:  
            return NULL;  
        }  
        return &memory_storage;  
     }  
     else {  
        // the band-sequential memory storage device cannot emulate any  
        // other storage types at this time  
        return NULL;  
     }  
  }  
  
  //  
  //  Routine to move images from the current device to the named device  
  //  This is the propagate-from-this-device call  
  //  
  XilDeviceStorage* XilDeviceStorageBandMemory::propagateDeviceStorage(char  
  type_name[])  
  {  
     XilDeviceStorage* new_storage_device;  
     XilMemoryStorage* memory_storage;  
  
     if (strcmp(type_name,"band_memory")==NULL) {  
        // it is already on the specified device  
        return NULL;  
  
     } else {  
        // get the storage type so we can access the device that the image  
        // will be going to  
        XilDeviceStorageType* storage_type;  
        storage_type=xil_global_state->getDeviceStorageType(type_name);  

Code Example 5-4 XilDeviceStorageTypeBandMemory.cc (10 of 17)

        if (storage_type==NULL) {  
           return NULL;  
        }  
        XilDeviceStorage* storage_device;  
  
        // if it is the memory device then create a new memory image and  
        // copy if necessary  
        if(strcmp(type_name,"memory")==NULL) {  
  
            if((parent->getBands() == 1) || (dataType == XIL_BIT)){  
                // it is one band or XIL_BIT memory image -- don't need to copy it  
                XilMemoryStorage* mem_storage = new XilMemoryStorage;  
  
                mem_storage->byte.data            = storage.byte.data;  
                mem_storage->byte.scanline_stride = storage.byte.scanline_stride;  
                mem_storage->byte.pixel_stride    = 1;  
  
             // Let the memory device take it over  
                storage_device=  
                    storage_type->propagateDeviceStorage(parent,  
                                                         "memory",  
                                                         mem_storage,  
                                                         TRUE);  
                if(storage_device==NULL) {  
                    return NULL;  
                }  
  
            } else {  
                // it is a multi-band, non-bit memory image -- must copy  
  
                // create the memory image  
                storage_device=  
                    storage_type->propagateDeviceStorage(parent,NULL,NULL,TRUE);  
                if(storage_device==NULL) {  
                    return NULL;  
                }  
  
                // get the storage information  
                memory_storage=  
                    (XilMemoryStorage*)storage_device-  
  >requestStorageInfo("memory");  
                if (memory_storage==NULL) {  

Code Example 5-4 XilDeviceStorageTypeBandMemory.cc (11 of 17)

                    return NULL;  
                }  
  
             // do the copy  
                copyBandMemory2Memory(&storage,memory_storage,parent);  
             // however, since this is not implemented, clean up and fail  
             delete memory_storage;  
             return NULL;  
            }  
        } else {  
            // it is an image type that this handler does not know how to  
         // propagate to -- must copy it  
  
         // first ask the other handler if it knows how to propagate from  
  band_memory  
            storage_device= storage_type->propagateDeviceStorage(parent,  
                         "band_memory",&storage,TRUE);  
            if (storage_device==NULL) {  
             // The other handler doesn't know about band_memory:  
             //   Create a memory image and propagate to that.  Then tell  
             //   the other handler to propagate from memory to itself  
             //   (all handlers need to be able to do this)  
  
             //  
                // create the intermediate memory image:  
             //  
             //   get access to the memory storage device  
                storage_type = xil_global_state->getDeviceStorageType("memory");  
             //   create an instance of a memory image  
                storage_device=storage_type-  
  >propagateDeviceStorage(parent,NULL,NULL,TRUE);  
                if (storage_device==NULL) {  
                    return NULL;  
                }  
                // get the memory storage information of the memory image  
                memory_storage= (XilMemoryStorage*)storage_device-  
  >requestStorageInfo("memory");  
                if (memory_storage==NULL) {  
                    return NULL;  
                }  

Code Example 5-4 XilDeviceStorageTypeBandMemory.cc (12 of 17)

             // copy from band_memory to memory  
                copyBandMemory2Memory(&storage,memory_storage,parent);  
             // however, since this is not implemented, clean up and fail  
             delete memory_storage;  
             return NULL;  
  
             // tell the memory device handler to propagate to the requested type  
                new_storage_device=storage_device-  
  >propagateDeviceStorage(type_name);  
                if (new_storage_device==NULL) {  
                 return NULL;  
              }  
              return new_storage_device;  
           }  
        }  
        delete this;  
        return storage_device;  
     }  
  }  
  
  void XilDeviceStorageBandMemory::getPixel(unsigned short x, unsigned short y,  
                                   unsigned short band, unsigned short count,  
                                   float* data)  
  {  
     switch (parent->getDataType()) {  
      case XIL_BIT:  
        {  
           Xil_unsigned8* pixel_byte;  
           Xil_unsigned8 pixel_bit;  
           pixel_byte= storage.bit.data +  
                           band*storage.bit.band_stride +  
           y*storage.bit.scanline_stride;  
           pixel_byte= pixel_byte + ((long)storage.bit.offset+(long)x)/(long)8;  
           pixel_bit= (Xil_unsigned8)(1 <<  
  (((long)storage.bit.offset+(long)x)%(long)8));  
           for (unsigned short i=0; i<count; i++) {  
              *data++= (*pixel_byte & pixel_bit) ? 1.0 : 0.0;  
              pixel_byte= pixel_byte+storage.bit.band_stride;  
           }  
        }  
        break;  

Code Example 5-4 XilDeviceStorageTypeBandMemory.cc (13 of 17)

      case XIL_BYTE:  
        {  
           Xil_unsigned8* pixel;  
           pixel= storage.byte.data +  
       band*storage.byte.band_stride +  
       y*storage.byte.scanline_stride + x;  
           for (unsigned short i=0; i<count; i++) *data++ = *pixel++;  
        }  
        break;  
      case XIL_SHORT:  
        {  
           Xil_signed16* pixel;  
           pixel= storage.shrt.data +  
       band*storage.shrt.band_stride +  
       y*storage.shrt.scanline_stride + x;  
           for (unsigned short i=0; i<count; i++) *data++ = *pixel++;  
        }  
        break;  
      case XIL_FLOAT:  
        {  
           float* pixel;  
           pixel= storage.flt.data +  
       band*storage.flt.band_stride +  
       y*storage.flt.scanline_stride + x;  
           for (unsigned short i=0; i<count; i++) *data++ = *pixel++;  
        }  
        break;  
     }  
  }  
  
  void XilDeviceStorageBandMemory::setPixel(unsigned short x, unsigned short y,  
                                   unsigned short band, unsigned short count,  
                                   float* data)  
  {  
     switch (parent->getDataType()) {  
      case XIL_BIT:  
        {  
           Xil_unsigned8* pixel_byte;  
           Xil_unsigned8 pixel_bit;  
           pixel_byte= storage.bit.data+  
                           band*storage.bit.band_stride+  
           y*storage.bit.scanline_stride;  

Code Example 5-4 XilDeviceStorageTypeBandMemory.cc (14 of 17)

           pixel_byte= pixel_byte + ((long)storage.bit.offset+(long)x)/(long)8;  
           pixel_bit= (Xil_unsigned8)(1 <<  
  ((long)storage.bit.offset+(long)x)%(long)8);  
           for (unsigned short i=0; i<count; i++) {  
              if (*data < .5) {  
                 *pixel_byte &= ~pixel_bit;  
              } else {  
                 *pixel_byte |= pixel_bit;  
              }  
              pixel_byte= pixel_byte+storage.bit.band_stride;  
              data++;  
           }  
        }  
        break;  
      case XIL_BYTE:  
        {  
           Xil_unsigned8* pixel;  
           pixel= storage.byte.data +  
       band*storage.byte.band_stride +  
       y*storage.byte.scanline_stride + x;  
           for (unsigned short i=0; i<count; i++) {  
              if (*data > 254.5) {  
                 *pixel= 255;  
              } else if (*data < .5) {  
                 *pixel= 0;  
              } else {  
                 *pixel= (Xil_unsigned8)(*data + .5);  
              }  
              pixel++;  
              data++;  
           }  
        }  
        break;  
      case XIL_SHORT:  
        {  
           Xil_signed16* pixel;  
           pixel= storage.shrt.data +  
       band*storage.shrt.band_stride +  
       y*storage.shrt.scanline_stride + x;  
           for (unsigned short i=0; i<count; i++) {  
              if (*data > 32766.5) {  
                 *pixel= 32767;  

Code Example 5-4 XilDeviceStorageTypeBandMemory.cc (15 of 17)

              } else if (*data < -32768.5) {  
                 *pixel= -32768;  
              } else if (*data > 0.0) {  
                 *pixel= (Xil_signed16)(*data + .5);  
              } else {  
                 *pixel= (Xil_signed16)(*data - .5);  
              }  
              pixel++;  
              data++;  
           }  
        }  
        break;  
      case XIL_FLOAT:  
        {  
           float* pixel;  
           pixel= storage.flt.data +  
       band*storage.flt.band_stride +  
       y*storage.flt.scanline_stride + x;  
           for (unsigned short i=0; i<count; i++) *pixel++ = *data++;  
        }  
        break;  
     }  
  }  
  
  XilBandMemoryStorage*  
  XilDeviceStorageTypeBandMemory::convertMemoryStorage(XilImage* image,  
                      XilMemoryStorage* memory_storage,  
                      Xil_boolean* need_copy)  
  {  
     // allocate a storage description  
     XilBandMemoryStorage* storage = new XilBandMemoryStorage;  
     if(storage == NULL)  
         return NULL;  
  
     // fill it in  
     XilDataType dataType= image->getDataType();  
     switch (dataType) {  
      case XIL_BIT:  
        storage->bit.data= memory_storage->bit.data;  
        storage->bit.offset= memory_storage->bit.offset;  
        storage->bit.scanline_stride= memory_storage->bit.scanline_stride;  

Code Example 5-4 XilDeviceStorageTypeBandMemory.cc (16 of 17)

        storage->bit.band_stride= memory_storage->bit.band_stride;  
        break;  
      case XIL_BYTE:  
        storage->byte.data= memory_storage->byte.data;  
        storage->byte.scanline_stride= memory_storage->byte.scanline_stride;  
        storage->byte.band_stride= memory_storage->byte.scanline_stride *  
                 image->getHeight();  
        break;  
      case XIL_SHORT:  
        storage->shrt.data= memory_storage->shrt.data;  
        storage->shrt.scanline_stride= memory_storage->shrt.scanline_stride;  
        storage->shrt.band_stride= memory_storage->shrt.scanline_stride *  
                 image->getHeight();  
        break;  
      case XIL_FLOAT:  
        storage->flt.data= memory_storage->flt.data;  
        storage->flt.scanline_stride= memory_storage->flt.scanline_stride;  
        storage->flt.band_stride= memory_storage->flt.scanline_stride *  
                 image->getHeight();  
        break;  
     }  
  
     // check if a copy is necessary  
     if ((image->getBands() == 1) || (dataType == XIL_BIT)) {  
        // 1-banded band_memory images have the same storage representation as  
        // memory images.  Also, 1-bit memory images are already band-sequential.  
        // In either of these cases, we do not need to reformat (copy) the data.  
        *need_copy = FALSE;  
     }  
     else {  
        // otherwise, we do  
        *need_copy = TRUE;  
     }  
  
     return(storage);  
  }  
  
  void  
  copyMemory2BandMemory(  XilMemoryStorage *memory_storage,  
                          XilBandMemoryStorage *storage,  
                          XilImage *parent)  

Code Example 5-4 XilDeviceStorageTypeBandMemory.cc (17 of 17)

  {  
  }  
  
  void  
  copyBandMemory2Memory(  XilBandMemoryStorage *storage,  
                          XilMemoryStorage *memory_storage,  
                          XilImage *parent)  
  {  
  }