Show
Ignore:
Timestamp:
01/24/12 15:34:02 (2 years ago)
Author:
robert
Message:

Added support for using GL_UNPACK_ROW_LENGTH in conjunction with texture's + osg::Image via new RowLength?
parameter in osg::Image. To support this Image::setData(..) now has a new optional rowLength parameter which
defaults to 0, which provides the original behaviour, Image::setRowLength(int) and int Image::getRowLength() are also provided.

With the introduction of RowLength? support in osg::Image it is now possible to create a sub image where
the t size of the image are smaller than the row length, useful for when you have a large image on the CPU
and which to use a small portion of it on the GPU. However, when these sub images are created the data
within the image is no longer contiguous so data access can no longer assume that all the data is in
one block. The new method Image::isDataContiguous() enables the user to check whether the data is contiguous,
and if not one can either access the data row by row using Image::data(column,row,image) accessor, or use the
new Image::DataIterator? for stepping through each block on memory assocatied with the image.

To support the possibility of non contiguous osg::Image usage of image objects has had to be updated to
check DataContiguous? and handle the case or use access via the DataIerator? or by row by row. To achieve
this a relatively large number of files has had to be modified, in particular the texture classes and
image plugins that doing writing.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • OpenSceneGraph/trunk/src/osg/Image.cpp

    r12842 r12912  
    4949} 
    5050 
     51Image::DataIterator::DataIterator(const Image* image): 
     52    _image(image), 
     53    _rowNum(0), 
     54    _imageNum(0), 
     55    _mipmapNum(0), 
     56    _currentPtr(0), 
     57    _currentSize(0) 
     58{ 
     59    assign(); 
     60} 
     61 
     62Image::DataIterator::DataIterator(const DataIterator& ri): 
     63    _image(ri._image), 
     64    _rowNum(ri._rowNum), 
     65    _imageNum(ri._imageNum), 
     66    _mipmapNum(ri._mipmapNum), 
     67    _currentPtr(0), 
     68    _currentSize(0) 
     69{ 
     70    assign(); 
     71} 
     72 
     73void Image::DataIterator::operator ++ () 
     74{ 
     75    if (!_image || _image->isDataContiguous()) 
     76    { 
     77        // for contiguous image data we never need more than one block of data 
     78        _currentPtr = 0; 
     79        _currentSize = 0; 
     80        return; 
     81    } 
     82 
     83    if (_image->isMipmap()) 
     84    { 
     85        // advance to next row 
     86        ++_rowNum; 
     87 
     88        if (_rowNum>=_image->t()) 
     89        { 
     90            // moved over end of current image so move to next 
     91            _rowNum = 0; 
     92            ++_imageNum; 
     93 
     94            if (_imageNum>=_image->r()) 
     95            { 
     96                // move to next mipmap 
     97                _imageNum = 0; 
     98                ++_mipmapNum; 
     99 
     100                if (_mipmapNum>=_image->getNumMipmapLevels()) 
     101                { 
     102                    _currentPtr = 0; 
     103                    _currentSize = 0; 
     104                    return; 
     105                } 
     106            } 
     107        } 
     108    } 
     109    else 
     110    { 
     111        // advance to next row 
     112        ++_rowNum; 
     113         
     114        if (_rowNum>=_image->t()) 
     115        { 
     116            // moved over end of current image so move to next 
     117            _rowNum = 0; 
     118            ++_imageNum; 
     119 
     120            if (_imageNum>=_image->r()) 
     121            { 
     122                // we've moved off the end of the osg::Image so reset to null 
     123                _currentPtr = 0; 
     124                _currentSize = 0; 
     125                return; 
     126            } 
     127        } 
     128    } 
     129    
     130    assign(); 
     131} 
     132 
     133void Image::DataIterator::assign() 
     134{ 
     135    //OSG_NOTICE<<"DataIterator::assign A"<<std::endl; 
     136    if (!_image) 
     137    { 
     138        _currentPtr = 0; 
     139        _currentSize = 0; 
     140        return; 
     141    } 
     142     
     143    //OSG_NOTICE<<"DataIterator::assign B"<<std::endl; 
     144 
     145    if (_image->isDataContiguous()) 
     146    { 
     147        _currentPtr = _image->data(); 
     148        _currentSize = _image->getTotalSizeInBytesIncludingMipmaps(); 
     149 
     150        //OSG_NOTICE<<"   _currentPtr="<<(void*)_currentPtr<<std::endl; 
     151        //OSG_NOTICE<<"   _currentSize="<<_currentSize<<std::endl; 
     152 
     153        return; 
     154    } 
     155     
     156    //OSG_NOTICE<<"DataIterator::assign C"<<std::endl; 
     157 
     158    if (_image->isMipmap()) 
     159    { 
     160        //OSG_NOTICE<<"DataIterator::assign D"<<std::endl; 
     161 
     162        if (_mipmapNum>=_image->getNumMipmapLevels()) 
     163        { 
     164            _currentPtr = 0; 
     165            _currentSize = 0; 
     166            return; 
     167        } 
     168        const unsigned char* ptr = _image->getMipmapData(_mipmapNum); 
     169         
     170        int rowLength = _image->getRowLength()>>_mipmapNum; 
     171        if (rowLength==0) rowLength = 1; 
     172         
     173        int imageHeight = _image->t()>>_mipmapNum; 
     174        if (imageHeight==0) imageHeight = 1; 
     175         
     176        unsigned int rowWidthInBytes = Image::computeRowWidthInBytes(rowLength,_image->getPixelFormat(),_image->getDataType(),_image->getPacking()); 
     177        unsigned int imageSizeInBytes = rowWidthInBytes*imageHeight; 
     178         
     179        _currentPtr = ptr + rowWidthInBytes*_rowNum + imageSizeInBytes*_imageNum; 
     180        _currentSize = rowWidthInBytes; 
     181    } 
     182    else 
     183    { 
     184        //OSG_NOTICE<<"DataIterator::assign E"<<std::endl; 
     185 
     186        if (_imageNum>=_image->r() || _rowNum>=_image->t()) 
     187        { 
     188            _currentPtr = 0; 
     189            _currentSize = 0; 
     190            return; 
     191        } 
     192 
     193        //OSG_NOTICE<<"DataIterator::assign F"<<std::endl; 
     194 
     195        _currentPtr = _image->data(0, _rowNum, _imageNum); 
     196        _currentSize = _image->getRowSizeInBytes(); 
     197        return; 
     198    } 
     199} 
     200 
     201 
    51202Image::Image() 
    52203    :BufferData(), 
     
    55206    _origin(BOTTOM_LEFT), 
    56207    _s(0), _t(0), _r(0), 
     208    _rowLength(0), 
    57209    _internalTextureFormat(0), 
    58210    _pixelFormat(0), 
     
    72224    _origin(image._origin), 
    73225    _s(image._s), _t(image._t), _r(image._r), 
     226    _rowLength(0), 
    74227    _internalTextureFormat(image._internalTextureFormat), 
    75228    _pixelFormat(image._pixelFormat), 
     
    85238        int size = image.getTotalSizeInBytesIncludingMipmaps(); 
    86239        setData(new unsigned char [size],USE_NEW_DELETE); 
    87         memcpy(_data,image._data,size); 
     240        unsigned char* dest_ptr = _data; 
     241        for(DataIterator itr(&image); itr.valid(); ++itr) 
     242        { 
     243            memcpy(dest_ptr, itr.data(), itr.size()); 
     244            dest_ptr += itr.size(); 
     245        } 
    88246    } 
    89247} 
     
    511669} 
    512670 
     671unsigned int Image::computeBlockSize(GLenum pixelFormat, GLenum packing) 
     672{ 
     673    switch(pixelFormat) 
     674    { 
     675        case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT): 
     676        case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT): 
     677            return osg::maximum(8u,packing); // block size of 8 
     678        case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT): 
     679        case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT): 
     680        case(GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG): 
     681        case(GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG): 
     682        case(GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG): 
     683        case(GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG): 
     684        case(GL_ETC1_RGB8_OES): 
     685            return osg::maximum(16u,packing); // block size of 16 
     686        case(GL_COMPRESSED_SIGNED_RED_RGTC1_EXT): 
     687        case(GL_COMPRESSED_RED_RGTC1_EXT): 
     688            return osg::maximum(8u,packing); // block size of 8 
     689            break; 
     690        case(GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT): 
     691        case(GL_COMPRESSED_RED_GREEN_RGTC2_EXT): 
     692            return osg::maximum(16u,packing); // block size of 16 
     693        default: 
     694            break; 
     695    } 
     696    return packing; 
     697} 
     698 
    513699unsigned int Image::computeRowWidthInBytes(int width,GLenum pixelFormat,GLenum type,int packing) 
    514700{ 
     
    518704    //OSG_INFO << "width="<<width<<" pixelSize="<<pixelSize<<"  width in bit="<<widthInBits<<" packingInBits="<<packingInBits<<" widthInBits%packingInBits="<<widthInBits%packingInBits<<std::endl; 
    519705    return (widthInBits/packingInBits + ((widthInBits%packingInBits)?1:0))*packing; 
     706} 
     707 
     708unsigned int Image::computeImageSizeInBytes(int width,int height, int depth, GLenum pixelFormat,GLenum type,int packing) 
     709{ 
     710    if (width==0 || height==0 || depth==0) return 0; 
     711     
     712    return osg::maximum( 
     713            Image::computeRowWidthInBytes(width,pixelFormat,type,packing)*height*depth, 
     714            computeBlockSize(pixelFormat, packing) 
     715        ); 
    520716} 
    521717 
     
    582778    int t = _t; 
    583779    int r = _r; 
    584      
    585     unsigned int maxValue = 0; 
    586     for(unsigned int i=0;i<_mipmapData.size() && _mipmapData[i];++i) 
    587     { 
     780    unsigned int totalSize = 0; 
     781    for(unsigned int i=0;i<_mipmapData.size()+1;++i) 
     782    { 
     783        totalSize += computeImageSizeInBytes(s, t, r, _pixelFormat, _dataType, _packing); 
     784         
    588785        s >>= 1; 
    589786        t >>= 1; 
    590787        r >>= 1; 
    591         maxValue = maximum(maxValue,_mipmapData[i]); 
     788 
     789        if (s<1) s=1; 
     790        if (t<1) t=1; 
     791        if (r<1) r=1; 
    592792   } 
    593     
    594    if (s==0) s=1; 
    595    if (t==0) t=1; 
    596    if (r==0) r=1; 
    597     
    598    unsigned int sizeOfLastMipMap = computeRowWidthInBytes(s,_pixelFormat,_dataType,_packing)* r*t; 
    599    switch(_pixelFormat) 
    600    { 
    601         case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT): 
    602         case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT): 
    603            sizeOfLastMipMap = maximum(sizeOfLastMipMap, 8u); // block size of 8 
    604            break; 
    605         case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT): 
    606         case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT): 
    607         case(GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG): 
    608         case(GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG): 
    609         case(GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG): 
    610         case(GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG): 
    611         case(GL_ETC1_RGB8_OES): 
    612            sizeOfLastMipMap = maximum(sizeOfLastMipMap, 16u); // block size of 16 
    613            break; 
    614         case(GL_COMPRESSED_SIGNED_RED_RGTC1_EXT): 
    615         case(GL_COMPRESSED_RED_RGTC1_EXT): 
    616             sizeOfLastMipMap = maximum(sizeOfLastMipMap, 8u); // block size of 8 
    617             break; 
    618         case(GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT): 
    619         case(GL_COMPRESSED_RED_GREEN_RGTC2_EXT): 
    620             sizeOfLastMipMap = maximum(sizeOfLastMipMap, 16u); // block size of 8 
    621             break; 
    622         default: break; 
    623    } 
    624  
    625    // OSG_INFO<<"sizeOfLastMipMap="<<sizeOfLastMipMap<<"\ts="<<s<<"\tt="<<t<<"\tr"<<r<<std::endl;                   
    626  
    627    return maxValue+sizeOfLastMipMap; 
    628  
     793 
     794   return totalSize; 
    629795} 
    630796 
     
    686852        _dataType = type; 
    687853        _packing = packing; 
     854        _rowLength = 0; 
    688855         
    689856        // preserve internalTextureFormat if already set, otherwise 
     
    701868        _dataType = 0; 
    702869        _packing = 0; 
     870        _rowLength = 0; 
    703871         
    704872        // commenting out reset of _internalTextureFormat as we are changing 
     
    715883                     unsigned char *data, 
    716884                     AllocationMode mode, 
    717                      int packing) 
     885                     int packing, 
     886                     int rowLength) 
    718887{ 
    719888    _mipmapData.clear(); 
     
    730899 
    731900    _packing = packing; 
     901    _rowLength = rowLength; 
    732902         
    733903    dirty(); 
     
    741911 
    742912    glPixelStorei(GL_PACK_ALIGNMENT,_packing); 
     913    glPixelStorei(GL_PACK_ROW_LENGTH,_rowLength); 
    743914 
    744915    glReadPixels(x,y,width,height,format,type,_data); 
     
    776947    GLint depth; 
    777948    GLint packing; 
     949    GLint rowLength; 
    778950 
    779951    GLint numMipMaps = 0; 
     
    8571029        glGetIntegerv(GL_UNPACK_ALIGNMENT, &packing); 
    8581030        glPixelStorei(GL_PACK_ALIGNMENT, packing); 
     1031        glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowLength); 
     1032        glPixelStorei(GL_PACK_ROW_LENGTH, rowLength); 
    8591033 
    8601034        _data = data; 
     
    8691043        _allocationMode=USE_NEW_DELETE; 
    8701044        _packing = packing; 
    871          
     1045        _rowLength = rowLength; 
     1046 
    8721047        for(i=0;i<numMipMaps;++i) 
    8731048        { 
     
    8871062        glGetIntegerv(GL_UNPACK_ALIGNMENT, &packing); 
    8881063        glPixelStorei(GL_PACK_ALIGNMENT, packing); 
     1064        glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowLength); 
     1065        glPixelStorei(GL_PACK_ROW_LENGTH, rowLength); 
    8891066 
    8901067        unsigned int total_size = 0; 
     
    9281105        _allocationMode=USE_NEW_DELETE; 
    9291106        _packing = packing; 
     1107        _rowLength = rowLength; 
    9301108         
    9311109        for(i=0;i<numMipMaps;++i) 
     
    9701148    PixelStorageModes psm; 
    9711149    psm.pack_alignment = _packing; 
     1150    psm.pack_row_length = _rowLength; 
    9721151    psm.unpack_alignment = _packing; 
    9731152 
     
    9881167        _s = s; 
    9891168        _t = t; 
     1169        _rowLength = 0; 
    9901170        _dataType = newDataType; 
    9911171        setData(newData,USE_NEW_DELETE); 
     
    10351215    PixelStorageModes psm; 
    10361216    psm.pack_alignment = _packing; 
    1037     psm.pack_row_length = _s; 
    1038     psm.unpack_alignment = _packing; 
     1217    psm.pack_row_length = _rowLength!=0 ? _rowLength : _s; 
     1218    psm.unpack_alignment = source->getPacking(); 
     1219    psm.unpack_row_length = source->getRowLength(); 
    10391220 
    10401221    GLint status = gluScaleImage(&psm, _pixelFormat, 
     
    10481229        data_destination); 
    10491230 
    1050     glPixelStorei(GL_PACK_ROW_LENGTH,0); 
    1051  
    10521231    if (status!=0) 
    10531232    { 
     
    10681247    if (_mipmapData.empty()) 
    10691248    { 
    1070  
     1249        unsigned int rowStepInBytes = getRowStepInBytes(); 
     1250        unsigned int imageStepInBytes = getImageStepInBytes(); 
     1251         
    10711252        for(int r=0;r<_r;++r) 
    10721253        { 
    10731254            for (int t=0; t<_t; ++t) 
    10741255            { 
    1075                 unsigned char* rowData = _data+t*getRowSizeInBytes()+r*getImageSizeInBytes(); 
     1256                unsigned char* rowData = _data + t*rowStepInBytes + r*imageStepInBytes; 
    10761257                unsigned char* left  = rowData ; 
    10771258                unsigned char* right = rowData + ((_s-1)*getPixelSizeInBits())/8; 
     
    10981279} 
    10991280 
    1100 void flipImageVertical(unsigned char* top, unsigned char* bottom, unsigned int rowSize) 
     1281void flipImageVertical(unsigned char* top, unsigned char* bottom, unsigned int rowSize, unsigned int rowStep) 
    11011282{ 
    11021283    while(top<bottom) 
    11031284    { 
    1104         for(unsigned int i=0;i<rowSize;++i, ++top,++bottom) 
    1105         { 
    1106             unsigned char temp=*top; 
    1107             *top = *bottom; 
    1108             *bottom = temp; 
    1109         } 
    1110         bottom -= 2*rowSize; 
     1285        unsigned char* t = top; 
     1286        unsigned char* b = bottom; 
     1287        for(unsigned int i=0;i<rowSize;++i, ++t,++b) 
     1288        { 
     1289            unsigned char temp=*t; 
     1290            *t = *b; 
     1291            *b = temp; 
     1292        } 
     1293        top += rowStep; 
     1294        bottom -= rowStep; 
    11111295    } 
    11121296} 
     
    11261310        return; 
    11271311    } 
     1312 
     1313    unsigned int rowSize = getRowSizeInBytes(); 
     1314    unsigned int rowStep = getRowStepInBytes(); 
    11281315 
    11291316    if (_mipmapData.empty()) 
     
    11361323            { 
    11371324                // its not a compressed image, so implement flip oursleves. 
    1138                  
    1139                 unsigned int rowSize = computeRowWidthInBytes(_s,_pixelFormat,_dataType,_packing); 
    11401325                unsigned char* top = data(0,0,r); 
    1141                 unsigned char* bottom = top + (_t-1)*rowSize; 
     1326                unsigned char* bottom = top + (_t-1)*rowStep; 
    11421327                     
    1143                 flipImageVertical(top, bottom, rowSize); 
     1328                flipImageVertical(top, bottom, rowSize, rowStep); 
    11441329            } 
    11451330        } 
     
    11501335        { 
    11511336            // its not a compressed image, so implement flip oursleves. 
    1152             unsigned int rowSize = computeRowWidthInBytes(_s,_pixelFormat,_dataType,_packing); 
    11531337            unsigned char* top = data(0,0,0); 
    1154             unsigned char* bottom = top + (_t-1)*rowSize; 
    1155  
    1156             flipImageVertical(top, bottom, rowSize); 
     1338            unsigned char* bottom = top + (_t-1)*rowStep; 
     1339 
     1340            flipImageVertical(top, bottom, rowSize, rowStep); 
    11571341        } 
    11581342 
     
    11701354            { 
    11711355                // its not a compressed image, so implement flip oursleves. 
    1172                 unsigned int rowSize = computeRowWidthInBytes(s,_pixelFormat,_dataType,_packing); 
    11731356                unsigned char* top = _data+_mipmapData[i]; 
    1174                 unsigned char* bottom = top + (t-1)*rowSize; 
    1175  
    1176                 flipImageVertical(top, bottom, rowSize); 
     1357                unsigned char* bottom = top + (t-1)*rowStep; 
     1358 
     1359                flipImageVertical(top, bottom, rowSize, rowStep); 
    11771360            } 
    11781361       } 
     
    12011384    } 
    12021385 
    1203     unsigned int sizeOfSlice = getImageSizeInBytes(); 
    1204  
    1205     int r_top = 0; 
    1206     int r_bottom = _r-1; 
    1207     for(; r_top<r_bottom; ++r_top,--r_bottom) 
    1208     { 
    1209         unsigned char* top_slice = data(0,0,r_top); 
    1210         unsigned char* bottom_slice = data(0,0,r_bottom); 
    1211         for(unsigned int i=0; i<sizeOfSlice; ++i, ++top_slice, ++bottom_slice) 
    1212         { 
    1213             std::swap(*top_slice, *bottom_slice); 
     1386    unsigned int sizeOfRow = getRowSizeInBytes(); 
     1387 
     1388    int r_front = 0; 
     1389    int r_back = _r-1; 
     1390    for(; r_front<r_back; ++r_front,--r_back) 
     1391    { 
     1392        for(int row=0; row<_t; ++row) 
     1393        {         
     1394            unsigned char* front = data(0, row, r_front); 
     1395            unsigned char* back = data(0, row, r_back); 
     1396            for(unsigned int i=0; i<sizeOfRow; ++i, ++front, ++back) 
     1397            { 
     1398                std::swap(*front, *back); 
     1399            } 
    12141400        } 
    12151401    } 
     
    14261612            dstate->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON); 
    14271613 
    1428             // set up the geoset. 
     1614            // set up the geoset.                unsigned int rowSize = computeRowWidthInBytes(s,_pixelFormat,_dataType,_packing); 
     1615 
    14291616            Geometry* geom = new Geometry; 
    14301617            geom->setStateSet(dstate);