Show
Ignore:
Timestamp:
05/23/08 18:26:03 (7 years ago)
Author:
robert
Message:

Added single buffered and double buffered PBO support, and --no-pbo,
--single-pbo and --double-pbo command line parameters

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • OpenSceneGraph/trunk/examples/osgscreencapture/osgscreencapture.cpp

    r8332 r8333  
    3737    public: 
    3838     
     39        enum Mode 
     40        { 
     41            READ_PIXELS, 
     42            SINGLE_PBO, 
     43            DOUBLE_PBO 
     44        }; 
     45     
    3946        struct ContextData : public osg::Referenced 
    4047        { 
    4148         
    42             ContextData(osg::GraphicsContext* gc, const std::string& name): 
     49            ContextData(osg::GraphicsContext* gc, Mode mode, const std::string& name): 
    4350                _gc(gc), 
     51                _mode(mode), 
    4452                _fileName(name), 
    4553                _pixelFormat(GL_RGB), 
     
    5866                 
    5967                // double buffer PBO. 
    60                 _pboBuffer.push_back(new osg::PixelBufferObject); 
    61                 _pboBuffer.push_back(new osg::PixelBufferObject); 
     68                switch(_mode) 
     69                { 
     70                    case(READ_PIXELS):  
     71                        osg::notify(osg::NOTICE)<<"Reading window usig glReadPixels, with out PixelBufferObject."<<std::endl; 
     72                        break; 
     73                    case(SINGLE_PBO):  
     74                        osg::notify(osg::NOTICE)<<"Reading window usig glReadPixels, with a single PixelBufferObject."<<std::endl; 
     75                        _pboBuffer.push_back(0);  
     76                        break; 
     77                    case(DOUBLE_PBO):  
     78                        osg::notify(osg::NOTICE)<<"Reading window usig glReadPixels, with a double buffer PixelBufferObject."<<std::endl; 
     79                        _pboBuffer.push_back(0);  
     80                        _pboBuffer.push_back(0);  
     81                        break; 
     82                    default: 
     83                        break;                                 
     84                } 
    6285            } 
    6386             
     
    7396            void read() 
    7497            { 
    75                 std::cout<<"Read to "<<_fileName<<" image "<<_currentImageIndex<<" "<<_currentPboIndex<<std::endl; 
    76                  
    77                 unsigned int nextImageIndex = (_currentImageIndex+1)%_imageBuffer.size(); 
    78                 unsigned int nextPboIndex = (_currentPboIndex+1)%_pboBuffer.size(); 
    79  
    80                 int width=0, height=0; 
    81                 getSize(_gc, width, height); 
    82                 if (width!=_width || _height!=height) 
     98                osg::BufferObject::Extensions* ext = osg::BufferObject::getExtensions(_gc->getState()->getContextID(),true); 
     99 
     100                if (ext->isPBOSupported() && !_pboBuffer.empty()) 
    83101                { 
    84                     std::cout<<"   Window resized "<<width<<", "<<height<<std::endl; 
    85                     _width = width; 
    86                     _height = height; 
     102                    if (_pboBuffer.size()==1) 
     103                    { 
     104                        singlePBO(ext); 
     105                    } 
     106                    else 
     107                    { 
     108                        multiPBO(ext); 
     109                    } 
    87110                } 
    88                  
    89                 osg::Image* image = _imageBuffer[_currentImageIndex].get(); 
    90                  
    91                 image->readPixels(0,0,_width,_height, 
    92                                   _pixelFormat,_type); 
    93                                     
    94                 if (!_fileName.empty()) 
     111                else 
    95112                { 
    96                     osgDB::writeImageFile(*image, _fileName); 
     113                    readPixels(); 
    97114                } 
    98                  
    99                 _currentImageIndex = nextImageIndex; 
    100                 _currentPboIndex = nextPboIndex; 
    101  
    102115            } 
     116             
     117            void readPixels(); 
     118 
     119            void singlePBO(osg::BufferObject::Extensions* ext); 
     120 
     121            void multiPBO(osg::BufferObject::Extensions* ext); 
    103122         
    104123            typedef std::vector< osg::ref_ptr<osg::Image> >             ImageBuffer; 
    105             typedef std::vector< osg::ref_ptr<osg::PixelBufferObject> > PBOBuffer; 
     124            typedef std::vector< GLuint > PBOBuffer; 
    106125         
    107126            osg::GraphicsContext*   _gc; 
     127            Mode                    _mode; 
    108128            std::string             _fileName; 
    109129             
     
    120140        }; 
    121141     
    122         WindowCaptureCallback() 
     142        WindowCaptureCallback(Mode mode): 
     143            _mode(mode) 
    123144        { 
    124145        } 
     
    128149            std::stringstream filename; 
    129150            filename << "test_"<<_contextDataMap.size()<<".jpg"; 
    130             return new ContextData(gc,filename.str()); 
     151            return new ContextData(gc, _mode, filename.str()); 
    131152        } 
    132153         
     
    143164        { 
    144165            osg::GraphicsContext* gc = renderInfo.getState()->getGraphicsContext(); 
    145             osg::notify(osg::NOTICE)<<"Capture screen image "<<gc<<std::endl; 
    146              
    147166            osg::ref_ptr<ContextData> cd = getContextData(gc); 
    148167            cd->read(); 
     
    150169         
    151170        typedef std::map<osg::GraphicsContext*, osg::ref_ptr<ContextData> > ContextDataMap; 
    152          
     171 
     172        Mode                        _mode;         
    153173        mutable OpenThreads::Mutex  _mutex; 
    154174        mutable ContextDataMap      _contextDataMap; 
    155175         
    156176}; 
     177 
     178void WindowCaptureCallback::ContextData::readPixels() 
     179{ 
     180    // std::cout<<"readPixels("<<_fileName<<" image "<<_currentImageIndex<<" "<<_currentPboIndex<<std::endl; 
     181 
     182    unsigned int nextImageIndex = (_currentImageIndex+1)%_imageBuffer.size(); 
     183    unsigned int nextPboIndex = _pboBuffer.empty() ? 0 : (_currentPboIndex+1)%_pboBuffer.size(); 
     184 
     185    int width=0, height=0; 
     186    getSize(_gc, width, height); 
     187    if (width!=_width || _height!=height) 
     188    { 
     189        std::cout<<"   Window resized "<<width<<", "<<height<<std::endl; 
     190        _width = width; 
     191        _height = height; 
     192    } 
     193 
     194    osg::Image* image = _imageBuffer[_currentImageIndex].get(); 
     195 
     196    image->readPixels(0,0,_width,_height, 
     197                      _pixelFormat,_type); 
     198 
     199    if (!_fileName.empty()) 
     200    { 
     201        // osgDB::writeImageFile(*image, _fileName); 
     202    } 
     203 
     204    _currentImageIndex = nextImageIndex; 
     205    _currentPboIndex = nextPboIndex; 
     206} 
     207 
     208void WindowCaptureCallback::ContextData::singlePBO(osg::BufferObject::Extensions* ext) 
     209{ 
     210    // std::cout<<"singelPBO(  "<<_fileName<<" image "<<_currentImageIndex<<" "<<_currentPboIndex<<std::endl; 
     211 
     212    unsigned int nextImageIndex = (_currentImageIndex+1)%_imageBuffer.size(); 
     213 
     214    int width=0, height=0; 
     215    getSize(_gc, width, height); 
     216    if (width!=_width || _height!=height) 
     217    { 
     218        std::cout<<"   Window resized "<<width<<", "<<height<<std::endl; 
     219        _width = width; 
     220        _height = height; 
     221    } 
     222 
     223    GLuint& pbo = _pboBuffer[0]; 
     224     
     225    osg::Image* image = _imageBuffer[_currentImageIndex].get(); 
     226    if (image->s() != _width ||  
     227        image->t() != _height) 
     228    { 
     229        osg::notify(osg::NOTICE)<<"Allocating image "<<std::endl; 
     230        image->allocateImage(_width, _height, 1, _pixelFormat, _type); 
     231         
     232        if (pbo!=0) 
     233        { 
     234            osg::notify(osg::NOTICE)<<"deleting pbo "<<pbo<<std::endl; 
     235            ext->glDeleteBuffers (1, &pbo); 
     236            pbo = 0; 
     237        } 
     238    } 
     239     
     240     
     241    if (pbo==0) 
     242    { 
     243        ext->glGenBuffers(1, &pbo); 
     244        ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pbo); 
     245        ext->glBufferData(GL_PIXEL_PACK_BUFFER_ARB, image->getTotalSizeInBytes(), 0, GL_STREAM_READ); 
     246 
     247        osg::notify(osg::NOTICE)<<"Generating pbo "<<pbo<<std::endl; 
     248    } 
     249    else 
     250    { 
     251        ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pbo); 
     252    } 
     253 
     254    glReadPixels(0, 0, _width, _height, _pixelFormat, _type, 0); 
     255 
     256    GLubyte* src = (GLubyte*)ext->glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, 
     257                                              GL_READ_ONLY_ARB); 
     258 
     259    if(src) 
     260    { 
     261        memcpy(image->data(), src, image->getTotalSizeInBytes()); 
     262 
     263        ext->glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB); 
     264    } 
     265 
     266    if (!_fileName.empty()) 
     267    { 
     268        // osgDB::writeImageFile(*image, _fileName); 
     269    } 
     270 
     271    ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0); 
     272 
     273    _currentImageIndex = nextImageIndex; 
     274} 
     275 
     276void WindowCaptureCallback::ContextData::multiPBO(osg::BufferObject::Extensions* ext) 
     277{ 
     278    // std::cout<<"multiPBO(  "<<_fileName<<" image "<<_currentImageIndex<<" "<<_currentPboIndex<<std::endl; 
     279    unsigned int nextImageIndex = (_currentImageIndex+1)%_imageBuffer.size(); 
     280    unsigned int nextPboIndex = (_currentPboIndex+1)%_pboBuffer.size(); 
     281 
     282    int width=0, height=0; 
     283    getSize(_gc, width, height); 
     284    if (width!=_width || _height!=height) 
     285    { 
     286        std::cout<<"   Window resized "<<width<<", "<<height<<std::endl; 
     287        _width = width; 
     288        _height = height; 
     289    } 
     290 
     291    GLuint& copy_pbo = _pboBuffer[_currentPboIndex]; 
     292    GLuint& read_pbo = _pboBuffer[nextPboIndex]; 
     293     
     294    osg::Image* image = _imageBuffer[_currentImageIndex].get(); 
     295    if (image->s() != _width ||  
     296        image->t() != _height) 
     297    { 
     298        osg::notify(osg::NOTICE)<<"Allocating image "<<std::endl; 
     299        image->allocateImage(_width, _height, 1, _pixelFormat, _type); 
     300         
     301        if (read_pbo!=0) 
     302        { 
     303            osg::notify(osg::NOTICE)<<"deleting pbo "<<read_pbo<<std::endl; 
     304            ext->glDeleteBuffers (1, &read_pbo); 
     305            read_pbo = 0; 
     306        } 
     307 
     308        if (copy_pbo!=0) 
     309        { 
     310            osg::notify(osg::NOTICE)<<"deleting pbo "<<copy_pbo<<std::endl; 
     311            ext->glDeleteBuffers (1, &copy_pbo); 
     312            copy_pbo = 0; 
     313        } 
     314    } 
     315     
     316     
     317    if (read_pbo==0) 
     318    { 
     319        ext->glGenBuffers(1, &read_pbo); 
     320        ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, read_pbo); 
     321        ext->glBufferData(GL_PIXEL_PACK_BUFFER_ARB, image->getTotalSizeInBytes(), 0, GL_STREAM_READ); 
     322 
     323        osg::notify(osg::NOTICE)<<"Generating pbo "<<read_pbo<<std::endl; 
     324    } 
     325    else 
     326    { 
     327        ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, read_pbo); 
     328    } 
     329 
     330    glReadPixels(0, 0, _width, _height, _pixelFormat, _type, 0); 
     331 
     332 
     333    if (copy_pbo!=0) 
     334    { 
     335 
     336        ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, copy_pbo); 
     337 
     338        GLubyte* src = (GLubyte*)ext->glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, 
     339                                                  GL_READ_ONLY_ARB); 
     340 
     341        if(src) 
     342        { 
     343            memcpy(image->data(), src, image->getTotalSizeInBytes()); 
     344 
     345            ext->glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB); 
     346        } 
     347 
     348        if (!_fileName.empty()) 
     349        { 
     350            // osgDB::writeImageFile(*image, _fileName); 
     351        } 
     352    } 
     353     
     354    ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0); 
     355 
     356    _currentImageIndex = nextImageIndex; 
     357    _currentPboIndex = nextPboIndex; 
     358} 
    157359 
    158360void addCallbackToViewer(osgViewer::ViewerBase& viewer, WindowCaptureCallback* callback) 
     
    282484    viewer.addEventHandler(new osgViewer::LODScaleHandler); 
    283485 
     486    WindowCaptureCallback::Mode mode = WindowCaptureCallback::DOUBLE_PBO; 
     487    while (arguments.read("--no-pbo")) mode = WindowCaptureCallback::READ_PIXELS; 
     488    while (arguments.read("--single-pbo")) mode = WindowCaptureCallback::SINGLE_PBO; 
     489    while (arguments.read("--double-pbo")) mode = WindowCaptureCallback::DOUBLE_PBO; 
     490         
    284491    // load the data 
    285492    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments); 
     
    309516    viewer.realize(); 
    310517     
    311     addCallbackToViewer(viewer, new WindowCaptureCallback); 
     518    addCallbackToViewer(viewer, new WindowCaptureCallback(mode)); 
    312519 
    313520    return viewer.run();