OpenWalnut
1.4.0
|
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