OpenWalnut  1.3.1
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  glReadBuffer( GL_BACK );
108 
109  // The following code uses PBO to grab the framebuffer. This sometimes causes errors. I am not sure why. glReadPixels
110  // osg::ref_ptr< osg::Image > imagePBO = new osg::Image();
111  // osg::BufferObject::Extensions* ext = osg::BufferObject::getExtensions( gc->getState()->getContextID(), true );
112  // imagePBO->allocateImage( width, height, 1, pixelFormat, GL_UNSIGNED_BYTE );
113  // if (m_pbo==0)
114  // {
115  // std::cout << "CREATE" << std::endl;
116  // ext->glGenBuffers( 1, &m_pbo );
117  // ext->glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, m_pbo );
118  // ext->glBufferData( GL_PIXEL_PACK_BUFFER_ARB, imagePBO->getTotalSizeInBytes(), 0, GL_STREAM_READ );
119  // }
120  // else
121  // {
122  // std::cout << "BIND" << std::endl;
123  // ext->glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, m_pbo );
124  // }
125  // std::cout << "READ" << std::endl;
126  // glReadPixels( 0, 0, width, height, pixelFormat, GL_UNSIGNED_BYTE, 0 );
127  // std::cout << "MAP" << std::endl;
128  // GLubyte* src = static_cast< GLubyte* >( ext->glMapBuffer( GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB ) );
129  // if(src)
130  // {
131  // std::cout << "COPY" << std::endl;
132  // memcpy( imagePBO->data(), src, imagePBO->getTotalSizeInBytes() );
133  // ext->glUnmapBuffer( GL_PIXEL_PACK_BUFFER_ARB );
134  //}
135  //
136  // std::cout << "RESTORE" << std::endl;
137  // ext->glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, 0 );
138 
139  // create image and read pixels into it
140  osg::ref_ptr< osg::Image > image = new osg::Image();
141  image->readPixels( 0, 0, width, height, pixelFormat, GL_UNSIGNED_BYTE );
142 
143  // another frame.
144  m_timer->tick();
145 
146  // someone wants this image
147  handleImage( frameCounter.m_framesLeft, frameCounter.m_frames, image );
148 }
149 
151 {
153 }
154 
156 {
158 }
159 
161 {
163  w->get().m_frames = 0;
164  m_timer->reset();
165 }
166 
167 void WGEScreenCapture::handleImage( size_t framesLeft, size_t totalFrames, osg::ref_ptr< osg::Image > image ) const
168 {
169  m_signalHandleImage( framesLeft, totalFrames, image );
170 }
171 
172 boost::signals2::connection WGEScreenCapture::subscribeSignal( HandleImageCallbackType callback )
173 {
174  return m_signalHandleImage.connect( callback );
175 }
176