OpenWalnut 1.3.1
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     glReadBuffer( GL_BACK );
00108 
00109     // The following code uses PBO to grab the framebuffer. This sometimes causes errors. I am not sure why. glReadPixels
00110     // osg::ref_ptr< osg::Image > imagePBO = new osg::Image();
00111     // osg::BufferObject::Extensions* ext = osg::BufferObject::getExtensions( gc->getState()->getContextID(), true );
00112     // imagePBO->allocateImage( width, height, 1, pixelFormat, GL_UNSIGNED_BYTE );
00113     // if (m_pbo==0)
00114     // {
00115     //     std::cout << "CREATE" << std::endl;
00116     //     ext->glGenBuffers( 1, &m_pbo );
00117     //     ext->glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, m_pbo );
00118     //     ext->glBufferData( GL_PIXEL_PACK_BUFFER_ARB, imagePBO->getTotalSizeInBytes(), 0, GL_STREAM_READ );
00119     // }
00120     // else
00121     // {
00122     //     std::cout << "BIND" << std::endl;
00123     //     ext->glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, m_pbo );
00124     // }
00125     // std::cout << "READ" << std::endl;
00126     // glReadPixels( 0, 0, width, height, pixelFormat, GL_UNSIGNED_BYTE, 0 );
00127     // std::cout << "MAP" << std::endl;
00128     // GLubyte* src = static_cast< GLubyte* >( ext->glMapBuffer( GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB ) );
00129     // if(src)
00130     // {
00131     //     std::cout << "COPY" << std::endl;
00132     //     memcpy( imagePBO->data(), src, imagePBO->getTotalSizeInBytes() );
00133     //     ext->glUnmapBuffer( GL_PIXEL_PACK_BUFFER_ARB );
00134     //}
00135     //
00136     // std::cout << "RESTORE" << std::endl;
00137     // ext->glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, 0 );
00138 
00139     // create image and read pixels into it
00140     osg::ref_ptr< osg::Image > image = new osg::Image();
00141     image->readPixels( 0, 0, width, height, pixelFormat, GL_UNSIGNED_BYTE );
00142 
00143     // another frame.
00144     m_timer->tick();
00145 
00146     // someone wants this image
00147     handleImage( frameCounter.m_framesLeft, frameCounter.m_frames, image );
00148 }
00149 
00150 WCondition::ConstSPtr WGEScreenCapture::getRecordCondition() const
00151 {
00152     return m_recordingInformation.getChangeCondition();
00153 }
00154 
00155 WGEScreenCapture::SharedRecordingInformation::ReadTicket WGEScreenCapture::getRecordingInformation() const
00156 {
00157     return m_recordingInformation.getReadTicket();
00158 }
00159 
00160 void WGEScreenCapture::resetFrameCounter()
00161 {
00162     SharedRecordingInformation::WriteTicket w = m_recordingInformation.getWriteTicket();
00163     w->get().m_frames = 0;
00164     m_timer->reset();
00165 }
00166 
00167 void WGEScreenCapture::handleImage( size_t framesLeft, size_t totalFrames, osg::ref_ptr< osg::Image > image ) const
00168 {
00169     m_signalHandleImage( framesLeft, totalFrames, image );
00170 }
00171 
00172 boost::signals2::connection WGEScreenCapture::subscribeSignal( HandleImageCallbackType callback )
00173 {
00174     return m_signalHandleImage.connect( callback );
00175 }
00176