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