Line data Source code
1 :
2 : /* Copyright (c) 2005-2014, Stefan Eilemann <eile@equalizergraphics.com>
3 : * 2010, Cedric Stalder <cedric Stalder@gmail.com>
4 : * 2011-2012, Daniel Nachbaur <danielnachbaur@gmail.com>
5 : *
6 : * This library is free software; you can redistribute it and/or modify it under
7 : * the terms of the GNU Lesser General Public License version 2.1 as published
8 : * by the Free Software Foundation.
9 : *
10 : * This library is distributed in the hope that it will be useful, but WITHOUT
11 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13 : * details.
14 : *
15 : * You should have received a copy of the GNU Lesser General Public License
16 : * along with this library; if not, write to the Free Software Foundation, Inc.,
17 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 : */
19 :
20 : #ifndef EQ_CONFIG_H
21 : #define EQ_CONFIG_H
22 :
23 : #include <eq/api.h>
24 : #include <eq/types.h>
25 :
26 : #include <eq/fabric/config.h> // base class
27 : #include <co/objectHandler.h> // base class
28 :
29 : namespace eq
30 : {
31 : namespace detail { class Config; }
32 :
33 : /**
34 : * A configuration is a visualization session driven by an application.
35 : *
36 : * The application Client can choose a configuration from a Server. The Config
37 : * will be instantiated though the NodeFactory. The Config groups all processes
38 : * of the application in a single session.
39 : *
40 : * A configuration has a number of nodes, which represent the processes involved
41 : * in it. While the Server drives all nodes, a Config instance in a given
42 : * process only has its Node instantiated, that is, any given Config has at most
43 : * one Node.
44 : *
45 : * The Config in the application process has access to all Canvas, Segment,
46 : * Layout, View and Observer instances. Only the active Layout of the each
47 : * Canvas, the Frustum of each View and the Observer parameters are
48 : * writable. Views can be sub-classed to attach application-specific data.
49 : *
50 : * The render client processes have only access to the current View for each of
51 : * their channels.
52 : *
53 : * @sa fabric::Config for public methods
54 : */
55 : class Config : public fabric::Config< Server, Config, Observer, Layout, Canvas,
56 : Node, ConfigVisitor >,
57 : public co::ObjectHandler
58 : {
59 : public:
60 : typedef fabric::Config< Server, Config, Observer, Layout, Canvas, Node,
61 : ConfigVisitor > Super; //!< base class
62 :
63 : /** Construct a new config. @version 1.0 */
64 : EQ_API explicit Config( ServerPtr parent );
65 :
66 : /** Destruct a config. @version 1.0 */
67 : EQ_API virtual ~Config();
68 :
69 : /** @name Data Access */
70 : //@{
71 : /** @return the local client node. @version 1.0 */
72 : EQ_API ClientPtr getClient();
73 :
74 : /** @return the local client node. @version 1.0 */
75 : EQ_API ConstClientPtr getClient() const;
76 :
77 : /**
78 : * @return the application node.
79 : * @warning experimental, may not be supported in the future
80 : */
81 : EQ_API co::NodePtr getApplicationNode();
82 :
83 : EQ_API co::CommandQueue* getMainThreadQueue(); //!< @internal
84 : EQ_API co::CommandQueue* getCommandThreadQueue(); //!< @internal
85 :
86 : /** @return the frame number of the last frame started. @version 1.0 */
87 : EQ_API uint32_t getCurrentFrame() const;
88 :
89 : /** @return the frame number of the last frame finished. @version 1.0 */
90 : EQ_API uint32_t getFinishedFrame() const;
91 :
92 : /** @internal Get all received statistics. */
93 : EQ_API GLStats::Data getStatistics() const;
94 :
95 : /**
96 : * @return true while the config is initialized and no exit event
97 : * has happened.
98 : * @version 1.0
99 : */
100 : EQ_API bool isRunning() const;
101 :
102 : /** Stop the config. @version 1.0 */
103 : EQ_API void stopRunning();
104 :
105 : /**
106 : * Get the current time in milliseconds.
107 : *
108 : * The clock in all processes of the config is synchronized to the Server
109 : * clock. The precision of this synchronization is typically about 1 ms. The
110 : * clock of the last instantiated config is used as the lunchbox::Log clock.
111 : *
112 : * @return the global time in ms.
113 : * @version 1.0
114 : */
115 : EQ_API int64_t getTime() const;
116 :
117 : /** @return the config's message pump, or 0. @version 1.0 */
118 : EQ_API MessagePump* getMessagePump();
119 :
120 : /** @internal */
121 0 : const Channel* findChannel( const std::string& name ) const
122 0 : { return find< Channel >( name ); }
123 : //@}
124 :
125 : /** @name Operations */
126 : //@{
127 : /**
128 : * Initialize this configuration.
129 : *
130 : * This method is to be called only on the application node on an
131 : * uninitialized configuration.
132 : *
133 : * Initializing a configuration starts and connects all render clients,
134 : * instantiates all active render entities (Node, Pipe, Window, Channel)
135 : * using the NodeFactory of each process, and calls the configInit task
136 : * methods on each of these entities, passing the given identifier.
137 : *
138 : * The identifier is typically the identifier of a static Object containing
139 : * initialization data.
140 : *
141 : * The initialization fails if at least one of the configInit task methods
142 : * fails. The application can use sendError() on the render client to pass
143 : * an error string to the application process, which is received by the
144 : * normal event processing.
145 : *
146 : * @param initID an identifier to be passed to all init methods.
147 : * @return true if the initialization was successful, false if not.
148 : * @version 1.0
149 : */
150 : EQ_API virtual bool init( const uint128_t& initID );
151 :
152 : /**
153 : * Exit this configuration.
154 : *
155 : * This method is to be called only on the application node on an
156 : * initialized configuration.
157 : *
158 : * Exiting a configuration calls configExit on all active render entities,
159 : * releases the entities using the NodeFactory and stops the render clients.
160 : *
161 : * A configuration which was not exited properly may not be re-initialized.
162 : *
163 : * @return true if the exit was successful, false if not.
164 : * @version 1.0
165 : */
166 : EQ_API virtual bool exit();
167 :
168 : /**
169 : * Update the configuration.
170 : *
171 : * This method is to be called only on the application node only on an
172 : * initialized configuration. Dirty objects on the config are committed,
173 : * i.e., the View, Canvas and Observer, and any changes to the configuration
174 : * are effected. Changes may be caused by the eq::admin API or by the
175 : * application, e.g., through a layout change on a Canvas. Any change causes
176 : * an implicit finish of all outstanding frames.
177 : *
178 : * This function always returns false when a resource failed to initialize
179 : * or exit. When robustness is not activated, the config is exited by the
180 : * update upon failure. When robustness is activated, the config keeps
181 : * running and may be used with reduced functionality.
182 : *
183 : * @return true if the configuration update was successful, false if a
184 : * resource failed to initialize or exit.
185 : * @version 1.0
186 : */
187 : EQ_API bool update();
188 :
189 : /** @sa fabric::Config::setLatency() */
190 : EQ_API void setLatency( const uint32_t latency ) override;
191 : //@}
192 :
193 : /** @name Object registry. */
194 : //@{
195 : /**
196 : * Register a distributed object.
197 : *
198 : * Provided for symmetry with deregisterObject. Forwards registration to
199 : * local client node.
200 : * @version 1.0
201 : */
202 : EQ_API bool registerObject( co::Object* object ) override;
203 :
204 : /**
205 : * Deregister a distributed object.
206 : *
207 : * This method ensures that the data for buffered object is kept for latency
208 : * frames to allow mapping on slave nodes.
209 : *
210 : * @param object the object instance.
211 : * @version 1.0
212 : */
213 : EQ_API void deregisterObject( co::Object* object ) override;
214 :
215 : /**
216 : * Map a distributed object.
217 : *
218 : * Provided for symmetry with deregisterObject. Forwards mapping to
219 : * local client node.
220 : * @version 1.0
221 : */
222 : EQ_API virtual bool mapObject( co::Object* object, const uint128_t& id,
223 : const uint128_t& version = co::VERSION_OLDEST );
224 :
225 :
226 : /** Start mapping a distributed object. @version 1.0 */
227 : EQ_API virtual uint32_t mapObjectNB( co::Object* object, const uint128_t& id,
228 : const uint128_t& version = co::VERSION_OLDEST );
229 :
230 : /** Start mapping a distributed object from a known master. @version 1.0 */
231 : EQ_API uint32_t mapObjectNB( co::Object* object,
232 : const uint128_t& id,
233 : const uint128_t& version,
234 : co::NodePtr master ) override;
235 :
236 : /** Finalize the mapping of a distributed object. @version 1.0 */
237 : EQ_API bool mapObjectSync( const uint32_t requestID ) override;
238 :
239 : /**
240 : * Unmap a mapped object.
241 : *
242 : * Provided for symmetry with deregisterObject. Forwards unmapping to
243 : * local client node.
244 : * @version 1.0
245 : */
246 : EQ_API void unmapObject( co::Object* object ) override;
247 :
248 : /**
249 : * Synchronize the local object with a remote object.
250 : *
251 : * Provided for symmetry. Forwards unmapping to local client node.
252 : * @version 1.7.4
253 : */
254 : EQ_API f_bool_t syncObject( co::Object* object, const uint128_t& id,
255 : co::NodePtr master,
256 : const uint32_t instanceID = CO_INSTANCE_ALL)
257 : override;
258 : //@}
259 :
260 : /** @name Frame Control */
261 : //@{
262 : /**
263 : * Request a new frame of rendering.
264 : *
265 : * This method is to be called only on the application node on an
266 : * initialized configuration. It implicitely calls update().
267 : *
268 : * The server will sync to the new data, and generate all render tasks,
269 : * which are queued on the render clients for execution.
270 : *
271 : * Each call to startFrame() has to be completed by a finishFrame() or
272 : * finishAllFrames() before the next call to startFrame().
273 : *
274 : * @param frameID a per-frame identifier passed to all rendering methods.
275 : * @return the frame number of the new frame.
276 : * @version 1.0
277 : */
278 : EQ_API virtual uint32_t startFrame( const uint128_t& frameID );
279 :
280 : /**
281 : * Finish the rendering of a frame.
282 : *
283 : * This method is to be called only on the application node on an
284 : * initialized configuration.
285 : *
286 : * This method synchronizes the local and global rendering. The global
287 : * rendering is always synchronized to finish the frame (current -
288 : * latency). The local rendering is synchronized according to the current
289 : * thread model (cf. Node::IATTR_THREAD_MODEL)
290 : *
291 : * @return the frame number of the globally finished frame, or 0 if no
292 : * frame has been finished yet.
293 : * @version 1.0
294 : */
295 : EQ_API virtual uint32_t finishFrame();
296 :
297 : /**
298 : * Finish rendering all pending frames.
299 : *
300 : * This method is to be called only on the application node on an
301 : * initialized configuration.
302 : *
303 : * @return the frame number of the last finished frame.
304 : * @version 1.0
305 : */
306 : EQ_API virtual uint32_t finishAllFrames();
307 :
308 : /**
309 : * Release the local synchronization of the config for a frame.
310 : *
311 : * Used by the local Node to release the process-local frame
312 : * synchronization. An application typically does not call this method
313 : * directly, it is called from Node::releaseFrameLocal(), which in turn is
314 : * called from the appropriate task method depending on the thread model.
315 : *
316 : * @param frameNumber the frame to release.
317 : * @version 1.0
318 : */
319 : EQ_API void releaseFrameLocal( const uint32_t frameNumber );
320 :
321 : /**
322 : * Asynchronously signal all channels to interrupt their rendering.
323 : *
324 : * This method may be called from any thread in the application process. It
325 : * causes Channel::notifyStopFrame() to be called immediately on all active
326 : * channels.
327 : *
328 : * @version 1.0
329 : */
330 : EQ_API void stopFrames();
331 :
332 : //@}
333 :
334 : /** @name Event handling */
335 : //@{
336 : #ifndef EQ_2_0_API
337 : /**
338 : * Get the next event.
339 : *
340 : * To be called only on the application node.
341 : *
342 : * The returned event is valid until the next call to this method. This
343 : * method may block.
344 : *
345 : * @return the event.
346 : * @deprecated
347 : * @sa Client::processCommand()
348 : */
349 : EQ_API const ConfigEvent* nextEvent();
350 :
351 : /**
352 : * Try to get the next event.
353 : *
354 : * To be called only on the application node.
355 : *
356 : * The returned event is valid until the next call to this method. This
357 : * method does not block.
358 : *
359 : * @return a config event, or 0 if no events are pending.
360 : * @deprecated
361 : */
362 : EQ_API const ConfigEvent* tryNextEvent();
363 : #endif
364 :
365 : /**
366 : * Send an (old) event to the application node.
367 : *
368 : * Should not be used by applications, other then sending any event defined
369 : * by Equalizer 1.5.0.
370 : *
371 : * @param event the event.
372 : * @deprecated
373 : */
374 : EQ_API void sendEvent( ConfigEvent& event );
375 :
376 : /**
377 : * Handle one (old) config event. Thread safe.
378 : *
379 : * This function handles all events which did exist in Equalizer
380 : * 1.5.0. Events introduced in 1.5.1 or later are handled by the other
381 : * handleEvent. Equalizer 2.0 will drop this method and send all events
382 : * using EventICommand instead of the ConfigEvent struct.
383 : *
384 : * @param event the event.
385 : * @return true if the event requires a redraw, false if not.
386 : */
387 : EQ_API virtual bool handleEvent( const ConfigEvent* event );
388 :
389 : /**
390 : * Send an event to the application node.
391 : *
392 : * The returned command can be used to pass additional data to the
393 : * event. The event will be send after the command is destroyed, aka when it
394 : * is running out of scope. Thread safe.
395 : *
396 : * @param type the event type.
397 : * @return the event command to pass additional data to
398 : * @version 1.5.1
399 : */
400 : EQ_API EventOCommand sendEvent( const uint32_t type );
401 :
402 : /**
403 : * Send an error event to the application node.
404 : *
405 : * @param type the error event type
406 : * @param error the error message.
407 : * @version 1.8.0
408 : */
409 : EQ_API EventOCommand sendError( const uint32_t type, const Error& error );
410 :
411 : /** @return the errors since the last call to this method.
412 : * @version 1.9
413 : */
414 : EQ_API Errors getErrors();
415 :
416 : /**
417 : * Get the next event.
418 : *
419 : * To be called only on the application node.
420 : *
421 : * The returned event command is valid until it gets out of scope. This
422 : * method does not block if the given timeout is 0. Not thread safe.
423 : *
424 : * @param timeout time in ms to wait for incoming events
425 : * @return the event command, or an invalid command on timeout
426 : * @version 1.5.1
427 : * @sa Client::processCommand()
428 : */
429 : EQ_API EventICommand getNextEvent( const uint32_t timeout =
430 : LB_TIMEOUT_INDEFINITE ) const;
431 :
432 : /**
433 : * Handle one config event. Thread safe.
434 : *
435 : * @param command the event command.
436 : * @return true if the event requires a redraw, false if not.
437 : * @version 1.5.1
438 : */
439 : EQ_API virtual bool handleEvent( EventICommand command );
440 :
441 : /** @return true if events are pending. Thread safe. @version 1.0 */
442 : EQ_API bool checkEvent() const;
443 :
444 : /**
445 : * Handle all config events.
446 : *
447 : * To be called only on the application node. Called automatically at the
448 : * end of each frame to handle pending config events. The default
449 : * implementation calls handleEvent() on all pending events, without
450 : * blocking. Not thread safe.
451 : * @version 1.0
452 : */
453 : EQ_API virtual void handleEvents();
454 :
455 : /**
456 : * Add an statistic event to the statistics overlay. Thread safe.
457 : *
458 : * @param originator the originator serial id.
459 : * @param stat the statistic event.
460 : * @warning experimental, may not be supported in the future
461 : */
462 : void addStatistic( const uint32_t originator, const Statistic& stat );
463 : //@}
464 :
465 : /**
466 : * @internal
467 : * Set up the config's message pump for the given pipe.
468 : * Used by non-threaded and AGL pipes.
469 : */
470 : void setupMessagePump( Pipe* pipe );
471 :
472 : /** @internal Set up appNode connections configured by server. */
473 : void setupServerConnections( const std::string& connectionData );
474 :
475 : protected:
476 : /** @internal */
477 : EQ_API void attach( const uint128_t& id,
478 : const uint32_t instanceID ) override;
479 :
480 : EQ_API void notifyAttached() override; //!< @internal
481 : EQ_API void notifyDetach() override; //!< @internal
482 : /** @internal */
483 : EQ_API void changeLatency( const uint32_t latency ) override;
484 : EQ_API bool mapViewObjects() const override; //!< @internal
485 :
486 : private:
487 : detail::Config* const _impl;
488 :
489 : void _frameStart();
490 : friend class Node;
491 :
492 : bool _needsLocalSync() const;
493 :
494 : bool _handleNewEvent( EventICommand& command );
495 : bool _handleEvent( const Event& event );
496 : const ConfigEvent* _convertEvent( co::ObjectICommand command );
497 :
498 : /** Update statistics for the last finished frame */
499 : void _updateStatistics();
500 :
501 : /** Release all deregistered buffered objects after their latency is
502 : done. */
503 : void _releaseObjects();
504 :
505 : /** Exit the current message pump */
506 : void _exitMessagePump();
507 :
508 : /** The command functions. */
509 : bool _cmdSyncClock( co::ICommand& command );
510 : bool _cmdCreateNode( co::ICommand& command );
511 : bool _cmdDestroyNode( co::ICommand& command );
512 : bool _cmdInitReply( co::ICommand& command );
513 : bool _cmdExitReply( co::ICommand& command );
514 : bool _cmdUpdateVersion( co::ICommand& command );
515 : bool _cmdUpdateReply( co::ICommand& command );
516 : bool _cmdReleaseFrameLocal( co::ICommand& command );
517 : bool _cmdFrameFinish( co::ICommand& command );
518 : bool _cmdSwapObject( co::ICommand& command );
519 : };
520 : }
521 :
522 : #endif // EQ_CONFIG_H
|