OpenWalnut  1.4.0
WGEScreenCapture.cpp
00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #include <osg/BufferObject>
00026 
00027 #include "animation/WGEAnimationFrameTimer.h"
00028 
00029 #include "WGEScreenCapture.h"
00030 
00031 WGEScreenCapture::WGEScreenCapture():
00032     m_timer( new WGEAnimationFrameTimer() )
00033 {
00034     // initialize
00035     SharedRecordingInformation::WriteTicket w = m_recordingInformation.getWriteTicket();
00036     w->get().m_frames = 0;
00037     w->get().m_framesLeft = 0;
00038 }
00039 
00040 WGEScreenCapture::~WGEScreenCapture()
00041 {
00042     // cleanup
00043 }
00044 
00045 WGEAnimationFrameTimer::ConstSPtr WGEScreenCapture::getFrameTimer() const
00046 {
00047     return m_timer;
00048 }
00049 
00050 void WGEScreenCapture::recordStart()
00051 {
00052     record();
00053 }
00054 
00055 void WGEScreenCapture::recordStop()
00056 {
00057     record( 0 );
00058 }
00059 
00060 void WGEScreenCapture::screenshot()
00061 {
00062     record( 1 );
00063 }
00064 
00065 void WGEScreenCapture::record( size_t frames )
00066 {
00067     SharedRecordingInformation::WriteTicket w = m_recordingInformation.getWriteTicket();
00068     w->get().m_framesLeft = frames;
00069 }
00070 
00071 bool WGEScreenCapture::isRecording()
00072 {
00073     SharedRecordingInformation::ReadTicket r = m_recordingInformation.getReadTicket();
00074     return r->get().m_framesLeft;
00075 }
00076 
00077 void WGEScreenCapture::operator()( osg::RenderInfo& renderInfo ) const  // NOLINT - osg wants this to be a non-const reference
00078 {
00079     SharedRecordingInformation::WriteTicket w = m_recordingInformation.getWriteTicket();
00080     RecordingInformation& frameCounter = w->get();
00081 
00082     // is there something to record?
00083     if( !frameCounter.m_framesLeft )
00084     {
00085         return;
00086     }
00087 
00088     // we need the graphics context here.
00089     osg::GraphicsContext* gc = renderInfo.getState()->getGraphicsContext();
00090 
00091     // get size and color mode
00092     size_t width = 0;
00093     size_t height = 0;
00094     GLenum pixelFormat = GL_RGB;
00095     if( gc->getTraits())
00096     {
00097         width = gc->getTraits()->width;
00098         height = gc->getTraits()->height;
00099         pixelFormat = gc->getTraits()->alpha ? GL_RGBA : GL_RGB;
00100     }
00101 
00102     // count frames
00103     frameCounter.m_frames++;
00104     frameCounter.m_framesLeft--;
00105 
00106     // read back buffer
00107 #ifndef GL_ES_VERSION_2_0
00108     glReadBuffer( GL_BACK );
00109 #endif
00110 
00111     // The following code uses PBO to grab the framebuffer. This sometimes causes errors. I am not sure why. glReadPixels
00112     // osg::ref_ptr< osg::Image > imagePBO = new osg::Image();
00113     // osg::BufferObject::Extensions* ext = osg::BufferObject::getExtensions( gc->getState()->getContextID(), true );
00114     // imagePBO->allocateImage( width, height, 1, pixelFormat, GL_UNSIGNED_BYTE );
00115     // if( m_pbo == 0 )
00116     // {
00117     //     std::cout << "CREATE" << std::endl;
00118     //     ext->glGenBuffers( 1, &m_pbo );
00119     //     ext->glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, m_pbo );
00120     //     ext->glBufferData( GL_PIXEL_PACK_BUFFER_ARB, imagePBO->getTotalSizeInBytes(), 0, GL_STREAM_READ );
00121     // }
00122     // else
00123     // {
00124     //     std::cout << "BIND" << std::endl;
00125     //     ext->glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, m_pbo );
00126     // }
00127     // std::cout << "READ" << std::endl;
00128     // glReadPixels( 0, 0, width, height, pixelFormat, GL_UNSIGNED_BYTE, 0 );
00129     // std::cout << "MAP" << std::endl;
00130     // GLubyte* src = static_cast< GLubyte* >( ext->glMapBuffer( GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB ) );
00131     // if(src)
00132     // {
00133     //     std::cout << "COPY" << std::endl;
00134     //     memcpy( imagePBO->data(), src, imagePBO->getTotalSizeInBytes() );
00135     //     ext->glUnmapBuffer( GL_PIXEL_PACK_BUFFER_ARB );
00136     //}
00137     //
00138     // std::cout << "RESTORE" << std::endl;
00139     // ext->glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, 0 );
00140 
00141     // create image and read pixels into it
00142     osg::ref_ptr< osg::Image > image = new osg::Image();
00143     image->readPixels( 0, 0, width, height, pixelFormat, GL_UNSIGNED_BYTE );
00144 
00145     // another frame.
00146     m_timer->tick();
00147 
00148     // someone wants this image
00149     handleImage( frameCounter.m_framesLeft, frameCounter.m_frames, image );
00150 }
00151 
00152 WCondition::ConstSPtr WGEScreenCapture::getRecordCondition() const
00153 {
00154     return m_recordingInformation.getChangeCondition();
00155 }
00156 
00157 WGEScreenCapture::SharedRecordingInformation::ReadTicket WGEScreenCapture::getRecordingInformation() const
00158 {
00159     return m_recordingInformation.getReadTicket();
00160 }
00161 
00162 void WGEScreenCapture::resetFrameCounter()
00163 {
00164     SharedRecordingInformation::WriteTicket w = m_recordingInformation.getWriteTicket();
00165     w->get().m_frames = 0;
00166     m_timer->reset();
00167 }
00168 
00169 void WGEScreenCapture::handleImage( size_t framesLeft, size_t totalFrames, osg::ref_ptr< osg::Image > image ) const
00170 {
00171     m_signalHandleImage( framesLeft, totalFrames, image );
00172 }
00173 
00174 boost::signals2::connection WGEScreenCapture::subscribeSignal( HandleImageCallbackType callback )
00175 {
00176     return m_signalHandleImage.connect( callback );
00177 }
00178