OpenWalnut  1.4.0
WGEScreenCapture.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <osg/BufferObject>
26 
27 #include "animation/WGEAnimationFrameTimer.h"
28 
29 #include "WGEScreenCapture.h"
30 
32  m_timer( new WGEAnimationFrameTimer() )
33 {
34  // initialize
36  w->get().m_frames = 0;
37  w->get().m_framesLeft = 0;
38 }
39 
41 {
42  // cleanup
43 }
44 
46 {
47  return m_timer;
48 }
49 
51 {
52  record();
53 }
54 
56 {
57  record( 0 );
58 }
59 
61 {
62  record( 1 );
63 }
64 
65 void WGEScreenCapture::record( size_t frames )
66 {
68  w->get().m_framesLeft = frames;
69 }
70 
72 {
74  return r->get().m_framesLeft;
75 }
76 
77 void WGEScreenCapture::operator()( osg::RenderInfo& renderInfo ) const // NOLINT - osg wants this to be a non-const reference
78 {
79  SharedRecordingInformation::WriteTicket w = m_recordingInformation.getWriteTicket();
80  RecordingInformation& frameCounter = w->get();
81 
82  // is there something to record?
83  if( !frameCounter.m_framesLeft )
84  {
85  return;
86  }
87 
88  // we need the graphics context here.
89  osg::GraphicsContext* gc = renderInfo.getState()->getGraphicsContext();
90 
91  // get size and color mode
92  size_t width = 0;
93  size_t height = 0;
94  GLenum pixelFormat = GL_RGB;
95  if( gc->getTraits())
96  {
97  width = gc->getTraits()->width;
98  height = gc->getTraits()->height;
99  pixelFormat = gc->getTraits()->alpha ? GL_RGBA : GL_RGB;
100  }
101 
102  // count frames
103  frameCounter.m_frames++;
104  frameCounter.m_framesLeft--;
105 
106  // read back buffer
107 #ifndef GL_ES_VERSION_2_0
108  glReadBuffer( GL_BACK );
109 #endif
110 
111  // The following code uses PBO to grab the framebuffer. This sometimes causes errors. I am not sure why. glReadPixels
112  // osg::ref_ptr< osg::Image > imagePBO = new osg::Image();
113  // osg::BufferObject::Extensions* ext = osg::BufferObject::getExtensions( gc->getState()->getContextID(), true );
114  // imagePBO->allocateImage( width, height, 1, pixelFormat, GL_UNSIGNED_BYTE );
115  // if( m_pbo == 0 )
116  // {
117  // std::cout << "CREATE" << std::endl;
118  // ext->glGenBuffers( 1, &m_pbo );
119  // ext->glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, m_pbo );
120  // ext->glBufferData( GL_PIXEL_PACK_BUFFER_ARB, imagePBO->getTotalSizeInBytes(), 0, GL_STREAM_READ );
121  // }
122  // else
123  // {
124  // std::cout << "BIND" << std::endl;
125  // ext->glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, m_pbo );
126  // }
127  // std::cout << "READ" << std::endl;
128  // glReadPixels( 0, 0, width, height, pixelFormat, GL_UNSIGNED_BYTE, 0 );
129  // std::cout << "MAP" << std::endl;
130  // GLubyte* src = static_cast< GLubyte* >( ext->glMapBuffer( GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB ) );
131  // if(src)
132  // {
133  // std::cout << "COPY" << std::endl;
134  // memcpy( imagePBO->data(), src, imagePBO->getTotalSizeInBytes() );
135  // ext->glUnmapBuffer( GL_PIXEL_PACK_BUFFER_ARB );
136  //}
137  //
138  // std::cout << "RESTORE" << std::endl;
139  // ext->glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, 0 );
140 
141  // create image and read pixels into it
142  osg::ref_ptr< osg::Image > image = new osg::Image();
143  image->readPixels( 0, 0, width, height, pixelFormat, GL_UNSIGNED_BYTE );
144 
145  // another frame.
146  m_timer->tick();
147 
148  // someone wants this image
149  handleImage( frameCounter.m_framesLeft, frameCounter.m_frames, image );
150 }
151 
153 {
155 }
156 
158 {
160 }
161 
163 {
165  w->get().m_frames = 0;
166  m_timer->reset();
167 }
168 
169 void WGEScreenCapture::handleImage( size_t framesLeft, size_t totalFrames, osg::ref_ptr< osg::Image > image ) const
170 {
171  m_signalHandleImage( framesLeft, totalFrames, image );
172 }
173 
174 boost::signals2::connection WGEScreenCapture::subscribeSignal( HandleImageCallbackType callback )
175 {
176  return m_signalHandleImage.connect( callback );
177 }
178