Line data Source code
1 :
2 : /* Copyright (c) 2005-2013, Stefan Eilemann <eile@equalizergraphics.com>
3 : * 2010, Cedric Stalder <cedric.stalder@gmail.com>
4 : *
5 : * This library is free software; you can redistribute it and/or modify it under
6 : * the terms of the GNU Lesser General Public License version 2.1 as published
7 : * by the Free Software Foundation.
8 : *
9 : * This library is distributed in the hope that it will be useful, but WITHOUT
10 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12 : * details.
13 : *
14 : * You should have received a copy of the GNU Lesser General Public License
15 : * along with this library; if not, write to the Free Software Foundation, Inc.,
16 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 : */
18 :
19 : #include "pipe.h"
20 :
21 : #include "channel.h"
22 : #include "config.h"
23 : #include "global.h"
24 : #include "log.h"
25 : #include "node.h"
26 : #include "nodeFactory.h"
27 : #include "window.h"
28 :
29 : #include <eq/fabric/commands.h>
30 : #include <eq/fabric/elementVisitor.h>
31 : #include <eq/fabric/paths.h>
32 :
33 : #include <co/objectICommand.h>
34 :
35 : namespace eq
36 : {
37 : namespace server
38 : {
39 :
40 : typedef fabric::Pipe< Node, Pipe, Window, PipeVisitor > Super;
41 : typedef co::CommandFunc<Pipe> PipeFunc;
42 :
43 588 : Pipe::Pipe( Node* parent )
44 : : Super( parent )
45 : , _active( 0 )
46 : , _state( STATE_STOPPED )
47 588 : , _lastDrawWindow( 0 )
48 : {
49 588 : const Global* global = Global::instance();
50 2352 : for( unsigned i = 0; i < IATTR_LAST; ++i )
51 : {
52 1764 : const IAttribute attr = static_cast< IAttribute >( i );
53 1764 : setIAttribute( attr, global->getPipeIAttribute( attr ));
54 : }
55 588 : }
56 :
57 1174 : Pipe::~Pipe()
58 : {
59 1174 : }
60 :
61 23 : void Pipe::attach( const uint128_t& id, const uint32_t instanceID )
62 : {
63 23 : Super::attach( id, instanceID );
64 :
65 23 : co::CommandQueue* cmdQ = getCommandThreadQueue();
66 : registerCommand( fabric::CMD_OBJECT_SYNC,
67 23 : PipeFunc( this, &Pipe::_cmdSync ), cmdQ );
68 : registerCommand( fabric::CMD_PIPE_CONFIG_INIT_REPLY,
69 23 : PipeFunc( this, &Pipe::_cmdConfigInitReply ), cmdQ );
70 : registerCommand( fabric::CMD_PIPE_CONFIG_EXIT_REPLY,
71 23 : PipeFunc( this, &Pipe::_cmdConfigExitReply ), cmdQ );
72 23 : }
73 :
74 0 : void Pipe::removeChild( const uint128_t& id )
75 : {
76 0 : LBASSERT( getConfig()->isRunning( ));
77 :
78 0 : Window* window = _findWindow( id );
79 0 : LBASSERT( window );
80 0 : if( window )
81 0 : window->postDelete();
82 0 : }
83 :
84 132 : ServerPtr Pipe::getServer()
85 : {
86 132 : Node* node = getNode();
87 132 : LBASSERT( node );
88 132 : return ( node ? node->getServer() : 0);
89 : }
90 :
91 0 : ConstServerPtr Pipe::getServer() const
92 : {
93 0 : const Node* node = getNode();
94 0 : LBASSERT( node );
95 0 : return node ? node->getServer() : 0;
96 : }
97 :
98 349 : Config* Pipe::getConfig()
99 : {
100 349 : Node* node = getNode();
101 349 : LBASSERT( node );
102 349 : return ( node ? node->getConfig() : 0);
103 : }
104 :
105 7 : const Config* Pipe::getConfig() const
106 : {
107 7 : const Node* node = getNode();
108 7 : LBASSERT( node );
109 7 : return ( node ? node->getConfig() : 0);
110 : }
111 :
112 109 : co::CommandQueue* Pipe::getMainThreadQueue()
113 : {
114 109 : Node* node = getNode();
115 109 : LBASSERT( node );
116 109 : return node->getMainThreadQueue();
117 : }
118 :
119 132 : co::CommandQueue* Pipe::getCommandThreadQueue()
120 : {
121 132 : Node* node = getNode();
122 132 : LBASSERT( node );
123 132 : return node->getCommandThreadQueue();
124 : }
125 :
126 0 : Channel* Pipe::getChannel( const ChannelPath& path )
127 : {
128 0 : const Windows& windows = getWindows();
129 0 : LBASSERTINFO( windows.size() > path.windowIndex,
130 : "Path " << path << " for " << *this );
131 :
132 0 : if( windows.size() <= path.windowIndex )
133 0 : return 0;
134 :
135 0 : return windows[ path.windowIndex ]->getChannel( path );
136 : }
137 :
138 22 : void Pipe::activate()
139 : {
140 22 : Node* node = getNode();
141 22 : LBASSERT( node );
142 :
143 22 : ++_active;
144 22 : if( node )
145 22 : node->activate();
146 :
147 22 : LBLOG( LOG_VIEW ) << "activate: " << _active << std::endl;
148 22 : }
149 :
150 22 : void Pipe::deactivate()
151 : {
152 22 : LBASSERT( _active != 0 );
153 :
154 22 : Node* node = getNode();
155 22 : LBASSERT( node );
156 :
157 22 : --_active;
158 22 : if( node )
159 22 : node->deactivate();
160 :
161 22 : LBLOG( LOG_VIEW ) << "deactivate: " << _active << std::endl;
162 22 : };
163 :
164 348 : void Pipe::addTasks( const uint32_t tasks )
165 : {
166 348 : Node* node = getNode();
167 348 : LBASSERT( node );
168 348 : setTasks( getTasks() | tasks );
169 348 : node->addTasks( tasks );
170 348 : }
171 :
172 66 : co::ObjectOCommand Pipe::send( const uint32_t cmd )
173 : {
174 66 : return getNode()->send( cmd, getID( ));
175 : }
176 :
177 : //===========================================================================
178 : // Operations
179 : //===========================================================================
180 :
181 : //---------------------------------------------------------------------------
182 : // init
183 : //---------------------------------------------------------------------------
184 15 : void Pipe::configInit( const uint128_t& initID, const uint32_t frameNumber )
185 : {
186 15 : LBASSERT( _state == STATE_STOPPED );
187 15 : _state = STATE_INITIALIZING;
188 :
189 15 : LBLOG( LOG_INIT ) << "Create pipe" << std::endl;
190 15 : getNode()->send( fabric::CMD_NODE_CREATE_PIPE, getNode()->getID( ))
191 30 : << getID() << isThreaded();
192 :
193 15 : LBLOG( LOG_INIT ) << "Init pipe" << std::endl;
194 15 : send( fabric::CMD_PIPE_CONFIG_INIT ) << initID << frameNumber;
195 15 : }
196 :
197 15 : bool Pipe::syncConfigInit()
198 : {
199 15 : LBASSERT( _state == STATE_INITIALIZING || _state == STATE_INIT_SUCCESS ||
200 : _state == STATE_INIT_FAILED );
201 :
202 15 : _state.waitNE( STATE_INITIALIZING );
203 :
204 15 : if( _state == STATE_INIT_SUCCESS )
205 : {
206 15 : _state = STATE_RUNNING;
207 15 : return true;
208 : }
209 :
210 0 : LBWARN << "Pipe initialization failed" << std::endl;
211 0 : configExit();
212 0 : return false;
213 : }
214 :
215 : //---------------------------------------------------------------------------
216 : // exit
217 : //---------------------------------------------------------------------------
218 15 : void Pipe::configExit()
219 : {
220 15 : if( _state == STATE_EXITING )
221 15 : return;
222 :
223 15 : LBASSERT( _state == STATE_RUNNING || _state == STATE_INIT_FAILED );
224 15 : _state = STATE_EXITING;
225 :
226 15 : LBLOG( LOG_INIT ) << "Exit pipe" << std::endl;
227 15 : send( fabric::CMD_PIPE_CONFIG_EXIT );
228 : }
229 :
230 15 : bool Pipe::syncConfigExit()
231 : {
232 15 : LBASSERT( _state == STATE_EXITING || _state == STATE_EXIT_SUCCESS ||
233 : _state == STATE_EXIT_FAILED );
234 :
235 15 : _state.waitNE( STATE_EXITING );
236 15 : const bool success = ( _state == STATE_EXIT_SUCCESS );
237 15 : LBASSERT( success || _state == STATE_EXIT_FAILED );
238 :
239 15 : _state = isActive() ? STATE_FAILED : STATE_STOPPED;
240 15 : setTasks( fabric::TASK_NONE );
241 15 : return success;
242 : }
243 :
244 : //---------------------------------------------------------------------------
245 : // update
246 : //---------------------------------------------------------------------------
247 7 : void Pipe::update( const uint128_t& frameID, const uint32_t frameNumber )
248 : {
249 7 : if( !isRunning( ))
250 7 : return;
251 :
252 7 : LBASSERT( isActive( ))
253 7 : send( fabric::CMD_PIPE_FRAME_START_CLOCK );
254 :
255 : send( fabric::CMD_PIPE_FRAME_START )
256 7 : << getVersion() << frameID << frameNumber;
257 7 : LBLOG( LOG_TASKS ) << "TASK pipe start frame " << frameNumber << " id "
258 7 : << frameID << std::endl;
259 :
260 7 : const Windows& windows = getWindows();
261 14 : for( Windows::const_iterator i = windows.begin(); i != windows.end(); ++i )
262 7 : (*i)->updateDraw( frameID, frameNumber );
263 :
264 14 : for( Windows::const_iterator i = windows.begin(); i != windows.end(); ++i )
265 7 : (*i)->updatePost( frameID, frameNumber );
266 :
267 7 : if( !_lastDrawWindow ) // no FrameDrawFinish sent
268 : {
269 0 : send( fabric::CMD_PIPE_FRAME_DRAW_FINISH ) << frameID << frameNumber;
270 0 : LBLOG( LOG_TASKS ) << "TASK pipe draw finish " << getName()
271 0 : << " frame " << frameNumber
272 0 : << " id " << frameID << std::endl;
273 : }
274 7 : _lastDrawWindow = 0;
275 :
276 7 : send( fabric::CMD_PIPE_FRAME_FINISH ) << frameID << frameNumber;
277 :
278 7 : LBLOG( LOG_TASKS ) << "TASK pipe finish frame " << frameNumber
279 7 : << " id " << frameID << std::endl;
280 : }
281 :
282 :
283 :
284 : //===========================================================================
285 : // command handling
286 : //===========================================================================
287 15 : bool Pipe::_cmdConfigInitReply( co::ICommand& cmd )
288 : {
289 15 : co::ObjectICommand command( cmd );
290 15 : const bool result = command.read< bool >();
291 :
292 15 : LBVERB << "handle pipe configInit reply " << command << " result " << result
293 15 : << std::endl;
294 :
295 15 : _state = result ? STATE_INIT_SUCCESS : STATE_INIT_FAILED;
296 15 : return true;
297 : }
298 :
299 15 : bool Pipe::_cmdConfigExitReply( co::ICommand& cmd )
300 : {
301 15 : co::ObjectICommand command( cmd );
302 15 : LBVERB << "handle pipe configExit reply " << command << std::endl;
303 :
304 15 : _state = command.read< bool >() ? STATE_EXIT_SUCCESS : STATE_EXIT_FAILED;
305 15 : return true;
306 : }
307 :
308 326 : void Pipe::output( std::ostream& os ) const
309 : {
310 326 : bool attrPrinted = false;
311 2608 : for( IAttribute i = static_cast<IAttribute>( 0 );
312 1304 : i < IATTR_LAST;
313 : i = static_cast<IAttribute>( static_cast<uint32_t>( i )+1))
314 : {
315 978 : const int value = getIAttribute( i );
316 978 : if( value == Global::instance()->getPipeIAttribute( i ))
317 973 : continue;
318 :
319 5 : if( !attrPrinted )
320 : {
321 5 : os << std::endl << "attributes" << std::endl;
322 5 : os << "{" << std::endl << lunchbox::indent;
323 5 : attrPrinted = true;
324 : }
325 :
326 : os << ( i == IATTR_HINT_THREAD ? "hint_thread " :
327 : i == IATTR_HINT_CUDA_GL_INTEROP ? "hint_cuda_GL_interop " :
328 : i == IATTR_HINT_AFFINITY ? "hint_affinity " :
329 5 : "ERROR" )
330 5 : << static_cast< fabric::IAttribute >( value ) << std::endl;
331 : }
332 :
333 326 : if( attrPrinted )
334 5 : os << lunchbox::exdent << "}" << std::endl;
335 326 : }
336 :
337 : }
338 : }
339 :
340 : #include "../fabric/pipe.ipp"
341 : template class eq::fabric::Pipe< eq::server::Node, eq::server::Pipe,
342 : eq::server::Window, eq::server::PipeVisitor >;
343 :
344 : /** @cond IGNORE */
345 : template std::ostream& eq::fabric::operator << ( std::ostream&,
346 27 : const eq::server::Super& );
347 : /** @endcond */
|