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 1146 : Pipe::Pipe( Node* parent )
44 : : Super( parent )
45 : , _active( 0 )
46 : , _state( STATE_STOPPED )
47 1146 : , _lastDrawWindow( 0 )
48 : {
49 1146 : const Global* global = Global::instance();
50 4584 : for( unsigned i = 0; i < IATTR_LAST; ++i )
51 : {
52 3438 : const IAttribute attr = static_cast< IAttribute >( i );
53 3438 : setIAttribute( attr, global->getPipeIAttribute( attr ));
54 : }
55 1146 : }
56 :
57 2288 : Pipe::~Pipe()
58 : {
59 2288 : }
60 :
61 4 : void Pipe::attach( const uint128_t& id, const uint32_t instanceID )
62 : {
63 4 : Super::attach( id, instanceID );
64 :
65 4 : co::CommandQueue* cmdQ = getCommandThreadQueue();
66 : registerCommand( fabric::CMD_OBJECT_SYNC,
67 4 : PipeFunc( this, &Pipe::_cmdSync ), cmdQ );
68 : registerCommand( fabric::CMD_PIPE_CONFIG_INIT_REPLY,
69 4 : PipeFunc( this, &Pipe::_cmdConfigInitReply ), cmdQ );
70 : registerCommand( fabric::CMD_PIPE_CONFIG_EXIT_REPLY,
71 4 : PipeFunc( this, &Pipe::_cmdConfigExitReply ), cmdQ );
72 4 : }
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 16 : ServerPtr Pipe::getServer()
85 : {
86 16 : Node* node = getNode();
87 16 : LBASSERT( node );
88 16 : 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 588 : Config* Pipe::getConfig()
99 : {
100 588 : Node* node = getNode();
101 588 : LBASSERT( node );
102 588 : return ( node ? node->getConfig() : 0);
103 : }
104 :
105 0 : const Config* Pipe::getConfig() const
106 : {
107 0 : const Node* node = getNode();
108 0 : LBASSERT( node );
109 0 : return ( node ? node->getConfig() : 0);
110 : }
111 :
112 12 : co::CommandQueue* Pipe::getMainThreadQueue()
113 : {
114 12 : Node* node = getNode();
115 12 : LBASSERT( node );
116 12 : return node->getMainThreadQueue();
117 : }
118 :
119 16 : co::CommandQueue* Pipe::getCommandThreadQueue()
120 : {
121 16 : Node* node = getNode();
122 16 : LBASSERT( node );
123 16 : 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 2 : void Pipe::activate()
139 : {
140 2 : Node* node = getNode();
141 2 : LBASSERT( node );
142 :
143 2 : ++_active;
144 2 : if( node )
145 2 : node->activate();
146 :
147 2 : LBLOG( LOG_VIEW ) << "activate: " << _active << std::endl;
148 2 : }
149 :
150 2 : void Pipe::deactivate()
151 : {
152 2 : LBASSERT( _active != 0 );
153 :
154 2 : Node* node = getNode();
155 2 : LBASSERT( node );
156 :
157 2 : --_active;
158 2 : if( node )
159 2 : node->deactivate();
160 :
161 2 : LBLOG( LOG_VIEW ) << "deactivate: " << _active << std::endl;
162 2 : };
163 :
164 4 : void Pipe::addTasks( const uint32_t tasks )
165 : {
166 4 : Node* node = getNode();
167 4 : LBASSERT( node );
168 4 : setTasks( getTasks() | tasks );
169 4 : node->addTasks( tasks );
170 4 : }
171 :
172 6 : co::ObjectOCommand Pipe::send( const uint32_t cmd )
173 : {
174 6 : return getNode()->send( cmd, getID( ));
175 : }
176 :
177 : //===========================================================================
178 : // Operations
179 : //===========================================================================
180 :
181 : //---------------------------------------------------------------------------
182 : // init
183 : //---------------------------------------------------------------------------
184 2 : void Pipe::configInit( const uint128_t& initID, const uint32_t frameNumber )
185 : {
186 2 : LBASSERT( _state == STATE_STOPPED );
187 2 : _state = STATE_INITIALIZING;
188 :
189 2 : LBLOG( LOG_INIT ) << "Create pipe" << std::endl;
190 2 : getNode()->send( fabric::CMD_NODE_CREATE_PIPE, getNode()->getID( ))
191 4 : << getID() << isThreaded();
192 :
193 2 : LBLOG( LOG_INIT ) << "Init pipe" << std::endl;
194 2 : send( fabric::CMD_PIPE_CONFIG_INIT ) << initID << frameNumber;
195 2 : }
196 :
197 2 : bool Pipe::syncConfigInit()
198 : {
199 2 : LBASSERT( _state == STATE_INITIALIZING || _state == STATE_INIT_SUCCESS ||
200 : _state == STATE_INIT_FAILED );
201 :
202 2 : _state.waitNE( STATE_INITIALIZING );
203 :
204 2 : if( _state == STATE_INIT_SUCCESS )
205 : {
206 0 : _state = STATE_RUNNING;
207 0 : return true;
208 : }
209 :
210 2 : LBWARN << "Pipe initialization failed" << std::endl;
211 2 : configExit();
212 2 : return false;
213 : }
214 :
215 : //---------------------------------------------------------------------------
216 : // exit
217 : //---------------------------------------------------------------------------
218 2 : void Pipe::configExit()
219 : {
220 2 : if( _state == STATE_EXITING )
221 2 : return;
222 :
223 2 : LBASSERT( _state == STATE_RUNNING || _state == STATE_INIT_FAILED );
224 2 : _state = STATE_EXITING;
225 :
226 2 : LBLOG( LOG_INIT ) << "Exit pipe" << std::endl;
227 2 : send( fabric::CMD_PIPE_CONFIG_EXIT );
228 : }
229 :
230 2 : bool Pipe::syncConfigExit()
231 : {
232 2 : LBASSERT( _state == STATE_EXITING || _state == STATE_EXIT_SUCCESS ||
233 : _state == STATE_EXIT_FAILED );
234 :
235 2 : _state.waitNE( STATE_EXITING );
236 2 : const bool success = ( _state == STATE_EXIT_SUCCESS );
237 2 : LBASSERT( success || _state == STATE_EXIT_FAILED );
238 :
239 2 : _state = isActive() ? STATE_FAILED : STATE_STOPPED;
240 2 : setTasks( fabric::TASK_NONE );
241 2 : return success;
242 : }
243 :
244 : //---------------------------------------------------------------------------
245 : // update
246 : //---------------------------------------------------------------------------
247 0 : void Pipe::update( const uint128_t& frameID, const uint32_t frameNumber )
248 : {
249 0 : if( !isRunning( ))
250 0 : return;
251 :
252 0 : LBASSERT( isActive( ))
253 0 : send( fabric::CMD_PIPE_FRAME_START_CLOCK );
254 :
255 : send( fabric::CMD_PIPE_FRAME_START )
256 0 : << getVersion() << frameID << frameNumber;
257 0 : LBLOG( LOG_TASKS ) << "TASK pipe start frame " << frameNumber << " id "
258 0 : << frameID << std::endl;
259 :
260 0 : const Windows& windows = getWindows();
261 0 : for( Windows::const_iterator i = windows.begin(); i != windows.end(); ++i )
262 0 : (*i)->updateDraw( frameID, frameNumber );
263 :
264 0 : for( Windows::const_iterator i = windows.begin(); i != windows.end(); ++i )
265 0 : (*i)->updatePost( frameID, frameNumber );
266 :
267 0 : 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 0 : _lastDrawWindow = 0;
275 :
276 0 : send( fabric::CMD_PIPE_FRAME_FINISH ) << frameID << frameNumber;
277 :
278 0 : LBLOG( LOG_TASKS ) << "TASK pipe finish frame " << frameNumber
279 0 : << " id " << frameID << std::endl;
280 : }
281 :
282 :
283 :
284 : //===========================================================================
285 : // command handling
286 : //===========================================================================
287 2 : bool Pipe::_cmdConfigInitReply( co::ICommand& cmd )
288 : {
289 2 : co::ObjectICommand command( cmd );
290 2 : const bool result = command.read< bool >();
291 :
292 2 : LBVERB << "handle pipe configInit reply " << command << " result " << result
293 2 : << std::endl;
294 :
295 2 : _state = result ? STATE_INIT_SUCCESS : STATE_INIT_FAILED;
296 2 : return true;
297 : }
298 :
299 2 : bool Pipe::_cmdConfigExitReply( co::ICommand& cmd )
300 : {
301 2 : co::ObjectICommand command( cmd );
302 2 : LBVERB << "handle pipe configExit reply " << command << std::endl;
303 :
304 2 : _state = command.read< bool >() ? STATE_EXIT_SUCCESS : STATE_EXIT_FAILED;
305 2 : return true;
306 : }
307 :
308 574 : void Pipe::output( std::ostream& os ) const
309 : {
310 574 : bool attrPrinted = false;
311 4592 : for( IAttribute i = static_cast<IAttribute>( 0 );
312 2296 : i < IATTR_LAST;
313 : i = static_cast<IAttribute>( static_cast<uint32_t>( i )+1))
314 : {
315 1722 : const int value = getIAttribute( i );
316 1722 : if( value == Global::instance()->getPipeIAttribute( i ))
317 1712 : continue;
318 :
319 10 : if( !attrPrinted )
320 : {
321 10 : os << std::endl << "attributes" << std::endl;
322 10 : os << "{" << std::endl << lunchbox::indent;
323 10 : 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 10 : "ERROR" )
330 10 : << static_cast< fabric::IAttribute >( value ) << std::endl;
331 : }
332 :
333 574 : if( attrPrinted )
334 10 : os << lunchbox::exdent << "}" << std::endl;
335 574 : }
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 84 : const eq::server::Super& );
347 : /** @endcond */
|