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/client/api.h>
24 : #include <eq/client/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 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 : 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 virtual void setLatency( const uint32_t latency );
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 virtual bool registerObject( co::Object* object );
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 virtual void deregisterObject( co::Object* object );
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 virtual uint32_t mapObjectNB( co::Object* object,
232 : const uint128_t& id,
233 : const uint128_t& version,
234 : co::NodePtr master );
235 :
236 : /** Finalize the mapping of a distributed object. @version 1.0 */
237 : EQ_API virtual bool mapObjectSync( const uint32_t requestID );
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 virtual void unmapObject( co::Object* object );
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, co::NodePtr master,
255 : const uint128_t& id,
256 : const uint32_t instanceID = CO_INSTANCE_ALL) override;
257 : //@}
258 :
259 : /** @name Frame Control */
260 : //@{
261 : /**
262 : * Request a new frame of rendering.
263 : *
264 : * This method is to be called only on the application node on an
265 : * initialized configuration. It implicitely calls update().
266 : *
267 : * The server will sync to the new data, and generate all render tasks,
268 : * which are queued on the render clients for execution.
269 : *
270 : * Each call to startFrame() has to be completed by a finishFrame() or
271 : * finishAllFrames() before the next call to startFrame().
272 : *
273 : * @param frameID a per-frame identifier passed to all rendering methods.
274 : * @return the frame number of the new frame.
275 : * @version 1.0
276 : */
277 : EQ_API virtual uint32_t startFrame( const uint128_t& frameID );
278 :
279 : /**
280 : * Finish the rendering of a frame.
281 : *
282 : * This method is to be called only on the application node on an
283 : * initialized configuration.
284 : *
285 : * This method synchronizes the local and global rendering. The global
286 : * rendering is always synchronized to finish the frame (current -
287 : * latency). The local rendering is synchronized according to the current
288 : * thread model (cf. Node::IATTR_THREAD_MODEL)
289 : *
290 : * @return the frame number of the globally finished frame, or 0 if no
291 : * frame has been finished yet.
292 : * @version 1.0
293 : */
294 : EQ_API virtual uint32_t finishFrame();
295 :
296 : /**
297 : * Finish rendering all pending frames.
298 : *
299 : * This method is to be called only on the application node on an
300 : * initialized configuration.
301 : *
302 : * @return the frame number of the last finished frame.
303 : * @version 1.0
304 : */
305 : EQ_API virtual uint32_t finishAllFrames();
306 :
307 : /**
308 : * Release the local synchronization of the config for a frame.
309 : *
310 : * Used by the local Node to release the process-local frame
311 : * synchronization. An application typically does not call this method
312 : * directly, it is called from Node::releaseFrameLocal(), which in turn is
313 : * called from the appropriate task method depending on the thread model.
314 : *
315 : * @param frameNumber the frame to release.
316 : * @version 1.0
317 : */
318 : EQ_API void releaseFrameLocal( const uint32_t frameNumber );
319 :
320 : /**
321 : * Asynchronously signal all channels to interrupt their rendering.
322 : *
323 : * This method may be called from any thread in the application process. It
324 : * causes Channel::notifyStopFrame() to be called immediately on all active
325 : * channels.
326 : *
327 : * @version 1.0
328 : */
329 : EQ_API void stopFrames();
330 :
331 : //@}
332 :
333 : /** @name Event handling */
334 : //@{
335 : #ifndef EQ_2_0_API
336 : /**
337 : * Get the next event.
338 : *
339 : * To be called only on the application node.
340 : *
341 : * The returned event is valid until the next call to this method. This
342 : * method may block.
343 : *
344 : * @return the event.
345 : * @deprecated
346 : * @sa Client::processCommand()
347 : */
348 : EQ_API const ConfigEvent* nextEvent();
349 :
350 : /**
351 : * Try to get the next event.
352 : *
353 : * To be called only on the application node.
354 : *
355 : * The returned event is valid until the next call to this method. This
356 : * method does not block.
357 : *
358 : * @return a config event, or 0 if no events are pending.
359 : * @deprecated
360 : */
361 : EQ_API const ConfigEvent* tryNextEvent();
362 : #endif
363 :
364 : /**
365 : * Send an (old) event to the application node.
366 : *
367 : * Should not be used by applications, other then sending any event defined
368 : * by Equalizer 1.5.0.
369 : *
370 : * @param event the event.
371 : * @deprecated
372 : */
373 : EQ_API void sendEvent( ConfigEvent& event );
374 :
375 : /**
376 : * Handle one (old) config event. Thread safe.
377 : *
378 : * This function handles all events which did exist in Equalizer
379 : * 1.5.0. Events introduced in 1.5.1 or later are handled by the other
380 : * handleEvent. Equalizer 2.0 will drop this method and send all events
381 : * using EventICommand instead of the ConfigEvent struct.
382 : *
383 : * @param event the event.
384 : * @return true if the event requires a redraw, false if not.
385 : */
386 : EQ_API virtual bool handleEvent( const ConfigEvent* event );
387 :
388 : /**
389 : * Send an event to the application node.
390 : *
391 : * The returned command can be used to pass additional data to the
392 : * event. The event will be send after the command is destroyed, aka when it
393 : * is running out of scope. Thread safe.
394 : *
395 : * @param type the event type.
396 : * @return the event command to pass additional data to
397 : * @version 1.5.1
398 : */
399 : EQ_API EventOCommand sendEvent( const uint32_t type );
400 :
401 : /**
402 : * Send an error event to the application node.
403 : *
404 : * @param type the error event type
405 : * @param originator the object identifier of the originator.
406 : * @param error the error message.
407 : * @version 1.7.1
408 : */
409 : EQ_API EventOCommand sendError( const uint32_t type,
410 : const uint128_t& originator,
411 : const uint32_t error );
412 : /**
413 : * Get the next event.
414 : *
415 : * To be called only on the application node.
416 : *
417 : * The returned event command is valid until it gets out of scope. This
418 : * method does not block if the given timeout is 0. Not thread safe.
419 : *
420 : * @param timeout time in ms to wait for incoming events
421 : * @return the event command.
422 : * @version 1.5.1
423 : * @sa Client::processCommand()
424 : */
425 : EQ_API EventICommand getNextEvent( const uint32_t timeout =
426 : LB_TIMEOUT_INDEFINITE ) const;
427 :
428 : /**
429 : * Handle one config event. Thread safe.
430 : *
431 : * @param command the event command.
432 : * @return true if the event requires a redraw, false if not.
433 : * @version 1.5.1
434 : */
435 : EQ_API virtual bool handleEvent( EventICommand command );
436 :
437 : /** @return true if events are pending. Thread safe. @version 1.0 */
438 : EQ_API bool checkEvent() const;
439 :
440 : /**
441 : * Handle all config events.
442 : *
443 : * To be called only on the application node. Called automatically at the
444 : * end of each frame to handle pending config events. The default
445 : * implementation calls handleEvent() on all pending events, without
446 : * blocking. Not thread safe.
447 : * @version 1.0
448 : */
449 : EQ_API virtual void handleEvents();
450 :
451 : /**
452 : * Add an statistic event to the statistics overlay. Thread safe.
453 : *
454 : * @param originator the originator serial id.
455 : * @param stat the statistic event.
456 : * @warning experimental, may not be supported in the future
457 : */
458 : void addStatistic( const uint32_t originator, const Statistic& stat );
459 : //@}
460 :
461 : /**
462 : * @internal
463 : * Set up the config's message pump for the given pipe.
464 : * Used by non-threaded and AGL pipes.
465 : */
466 : void setupMessagePump( Pipe* pipe );
467 :
468 : /** @internal Set up appNode connections configured by server. */
469 : void setupServerConnections( const std::string& connectionData );
470 :
471 : protected:
472 : /** @internal */
473 : EQ_API virtual void attach( const uint128_t& id,
474 : const uint32_t instanceID );
475 :
476 : EQ_API virtual void notifyAttached(); //!< @internal
477 : EQ_API virtual void notifyDetach(); //!< @internal
478 : /** @internal */
479 : EQ_API virtual void changeLatency( const uint32_t latency );
480 : EQ_API virtual bool mapViewObjects() const; //!< @internal
481 :
482 : private:
483 : detail::Config* const _impl;
484 :
485 : void _frameStart();
486 : friend class Node;
487 :
488 : bool _needsLocalSync() const;
489 :
490 : bool _handleNewEvent( EventICommand& command );
491 : bool _handleEvent( const Event& event );
492 : const ConfigEvent* _convertEvent( co::ObjectICommand command );
493 :
494 : /** Update statistics for the last finished frame */
495 : void _updateStatistics();
496 :
497 : /** Release all deregistered buffered objects after their latency is
498 : done. */
499 : void _releaseObjects();
500 :
501 : /** Exit the current message pump */
502 : void _exitMessagePump();
503 :
504 : /** The command functions. */
505 : bool _cmdSyncClock( co::ICommand& command );
506 : bool _cmdCreateNode( co::ICommand& command );
507 : bool _cmdDestroyNode( co::ICommand& command );
508 : bool _cmdInitReply( co::ICommand& command );
509 : bool _cmdExitReply( co::ICommand& command );
510 : bool _cmdUpdateVersion( co::ICommand& command );
511 : bool _cmdUpdateReply( co::ICommand& command );
512 : bool _cmdReleaseFrameLocal( co::ICommand& command );
513 : bool _cmdFrameFinish( co::ICommand& command );
514 : bool _cmdSwapObject( co::ICommand& command );
515 : };
516 : }
517 :
518 : #endif // EQ_CONFIG_H
|