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 EQSERVER_COMPOUND_H
21 : #define EQSERVER_COMPOUND_H
22 :
23 : #include "channel.h" // used in inline method
24 : #include "frustum.h" // member
25 : #include "frustumData.h" // member
26 : #include "types.h"
27 : #include "visitorResult.h" // enum
28 :
29 : #include <co/barrier.h>
30 : #include <eq/fabric/frame.h> // enum Frame::Buffer
31 : #include <eq/fabric/projection.h> // used in inline method
32 : #include <eq/fabric/range.h> // member
33 : #include <eq/fabric/subPixel.h> // member
34 : #include <eq/fabric/swapBarrier.h> // RefPtr member
35 : #include <eq/fabric/task.h> // enum
36 : #include <eq/fabric/viewport.h> // member
37 : #include <eq/fabric/wall.h> // used in inline method
38 : #include <eq/fabric/zoom.h> // member
39 : #include <iostream>
40 : #include <lunchbox/thread.h>
41 : #include <vector>
42 :
43 : namespace eq
44 : {
45 : namespace server
46 : {
47 : /** The compound form the tree describing the rendering task setup. */
48 : class Compound
49 : {
50 : public:
51 : /** Construct a new root compound. */
52 : EQSERVER_API explicit Compound(Config* parent);
53 :
54 : /** Construct a new compound child. */
55 : EQSERVER_API explicit Compound(Compound* parent);
56 :
57 : /** Destruct the compound and all children. */
58 : virtual ~Compound();
59 :
60 : /** The color mask bits, used for anaglyphic stereo. */
61 : enum ColorMask
62 : {
63 : COLOR_MASK_NONE = 0,
64 : COLOR_MASK_RED = 0x02,
65 : COLOR_MASK_GREEN = 0x04,
66 : COLOR_MASK_BLUE = 0x08,
67 : COLOR_MASK_ALL = 0xff
68 : };
69 :
70 : /**
71 : * @name Attributes
72 : */
73 : //@{
74 : // Note: also update string array initialization in compound.cpp
75 : enum IAttribute
76 : {
77 : IATTR_STEREO_MODE,
78 : IATTR_STEREO_ANAGLYPH_LEFT_MASK,
79 : IATTR_STEREO_ANAGLYPH_RIGHT_MASK,
80 : IATTR_FILL1,
81 : IATTR_FILL2,
82 : IATTR_ALL
83 : };
84 :
85 : /**
86 : * @name Data Access
87 : */
88 : //@{
89 : /** Reparent the given child to this compound. */
90 : EQSERVER_API void adopt(Compound* child);
91 :
92 : /** @return if the compound is a leaf compound. */
93 4230 : bool isLeaf() const { return _children.empty(); }
94 : /** @return true if this is the top-most compound with a channel. */
95 : bool isDestination() const;
96 :
97 : /** @return if the compound has the destination channel. */
98 : bool hasDestinationChannel() const;
99 :
100 : /** @return the children of this compound. */
101 12060 : const Compounds& getChildren() const { return _children; }
102 : /** @return the parent compound. */
103 28978 : Compound* getParent() const { return _parent; }
104 : /** @return the root of the compound tree. */
105 3546 : Compound* getRoot() { return _parent ? _parent->getRoot() : this; }
106 1516 : const Compound* getRoot() const
107 : {
108 1516 : return _parent ? _parent->getRoot() : this;
109 : }
110 :
111 : /** @return true if this is the top-most compound. */
112 660 : bool isRoot() const { return _parent == 0; }
113 : /** @return the next sibling, or 0. */
114 : Compound* getNext() const;
115 :
116 396 : Config* getConfig() { return getRoot()->_config; }
117 1516 : const Config* getConfig() const { return getRoot()->_config; }
118 : Node* getNode();
119 : ServerPtr getServer();
120 :
121 64 : void setName(const std::string& name) { _name = name; }
122 3072 : const std::string& getName() const { return _name; }
123 : /**
124 : * Set the channel of this compound.
125 : *
126 : * The compound uses the channel for all rendering operations executed
127 : * by this compound. The compound's swap barrier will be updated with
128 : * the segment's swap barrier if this compound becomes a destination
129 : * compound.
130 : *
131 : * @param channel the channel.
132 : */
133 : EQSERVER_API void setChannel(Channel* channel);
134 :
135 : /**
136 : * Return the channel of this compound.
137 : *
138 : * Note that the channel is inherited, that is, if this compound has no
139 : * channel, the parent's channel is returned.
140 : *
141 : * @return the channel of this compound.
142 : */
143 : EQSERVER_API Channel* getChannel();
144 : EQSERVER_API const Channel* getChannel() const;
145 :
146 : Window* getWindow();
147 : const Window* getWindow() const;
148 :
149 : Pipe* getPipe();
150 : const Pipe* getPipe() const;
151 :
152 : /** Attach a load balancer to this compound. */
153 : EQSERVER_API void addEqualizer(Equalizer* equalizer);
154 :
155 : /** Get the attached load balancers. */
156 2422 : const Equalizers& getEqualizers() const { return _equalizers; }
157 : /**
158 : * Set the tasks to be executed by the compound, overwriting previous
159 : * tasks.
160 : *
161 : * Tasks define which actions are executed by the compound, and provide
162 : * a flexible way of configuring the decomposition and recomposition. A
163 : * separate html design document describes them in depth.
164 : *
165 : * @param tasks the compound tasks.
166 : */
167 368 : void setTasks(const uint32_t tasks) { _data.tasks = tasks; }
168 : /**
169 : * Add a task to be executed by the compound, preserving previous tasks.
170 : *
171 : * @param task the compound task to add.
172 : */
173 560 : void enableTask(const fabric::Task task) { _data.tasks |= task; }
174 : /** @return the tasks executed by this compound. */
175 2304 : uint32_t getTasks() const { return _data.tasks; }
176 : /**
177 : * Set the image buffers to be used by the compound during
178 : * recomposition, overwriting previous buffers.
179 : *
180 : * @param buffers the compound image buffers.
181 : */
182 200 : void setBuffers(const fabric::Frame::Buffer buffers)
183 : {
184 200 : _data.buffers = buffers;
185 200 : }
186 :
187 : /**
188 : * Add a image buffer to be used by the compound, preserving previous
189 : * buffers.
190 : *
191 : * @param buffer the compound image buffer to add.
192 : */
193 : void enableBuffer(const fabric::Frame::Buffer buffer)
194 : {
195 : _data.buffers |= buffer;
196 : }
197 :
198 : /** @return the image buffers used by this compound. */
199 2304 : fabric::Frame::Buffer getBuffers() const { return _data.buffers; }
200 272 : void setViewport(const Viewport& vp) { _data.vp = vp; }
201 2304 : const Viewport& getViewport() const { return _data.vp; }
202 724 : void setRange(const Range& range) { _data.range = range; }
203 2304 : const Range& getRange() const { return _data.range; }
204 68 : void setPeriod(const uint32_t period) { _data.period = period; }
205 2304 : uint32_t getPeriod() const { return _data.period; }
206 68 : void setPhase(const uint32_t phase) { _data.phase = phase; }
207 2304 : uint32_t getPhase() const { return _data.phase; }
208 92 : void setPixel(const Pixel& pixel) { _data.pixel = pixel; }
209 2304 : const Pixel& getPixel() const { return _data.pixel; }
210 52 : void setSubPixel(const SubPixel& subPixel) { _data.subPixel = subPixel; }
211 2304 : const SubPixel& getSubPixel() const { return _data.subPixel; }
212 4 : void setZoom(const Zoom& zoom) { _data.zoom = zoom; }
213 2304 : const Zoom& getZoom() const { return _data.zoom; }
214 0 : void setMaxFPS(const float fps) { _data.maxFPS = fps; }
215 : float getMaxFPS() const { return _data.maxFPS; }
216 0 : void setUsage(const float usage)
217 : {
218 0 : LBASSERT(usage >= 0.f);
219 0 : _usage = usage;
220 0 : }
221 16 : float getUsage() const { return _usage; }
222 396 : void setTaskID(const uint32_t id) { _taskID = id; }
223 12 : uint32_t getTaskID() const { return _taskID; }
224 : //@}
225 :
226 : /** @name IO object access. */
227 : //@{
228 : /**
229 : * Set a swap barrier.
230 : *
231 : * Windows of compounds with the same swap barrier name will enter a
232 : * barrier before executing Window::swap. Setting an empty string
233 : * disables the swap barrier.
234 : *
235 : * @param barrier the swap barrier.
236 : */
237 : void setSwapBarrier(SwapBarrierPtr barrier);
238 :
239 : /** @return the current swap barrier. */
240 2580 : SwapBarrierConstPtr getSwapBarrier() const { return _swapBarrier; }
241 : /**
242 : * Add a new input frame for this compound.
243 : *
244 : * @param frame the input frame.
245 : */
246 : EQSERVER_API void addInputFrame(Frame* frame);
247 :
248 : /** @return the vector of input frames. */
249 2322 : const Frames& getInputFrames() const { return _inputFrames; }
250 : /**
251 : * Add a new output frame for this compound.
252 : *
253 : * @param frame the output frame.
254 : */
255 : EQSERVER_API void addOutputFrame(Frame* frame);
256 :
257 : /** @return the vector of output frames. */
258 2486 : const Frames& getOutputFrames() const { return _outputFrames; }
259 : /**
260 : * Add a new input tile queue for this compound.
261 : *
262 : * @param tileQueue the input tile queue.
263 : */
264 : EQSERVER_API void addInputTileQueue(TileQueue* tileQueue);
265 :
266 : /**
267 : * Remove an input tile queue from this compound.
268 : *
269 : * @param tileQueue the input tile queue.
270 : */
271 : EQSERVER_API void removeInputTileQueue(TileQueue* tileQueue);
272 :
273 : /** @return the vector of input tile queues. */
274 2352 : const TileQueues& getInputTileQueues() const { return _inputTileQueues; }
275 : /**
276 : * Add a new output tile queue for this compound.
277 : *
278 : * @param queue the output tile queue.
279 : */
280 : EQSERVER_API void addOutputTileQueue(TileQueue* queue);
281 :
282 : /**
283 : * Remove an output tile queue from this compound.
284 : *
285 : * @param tileQueue the output tile queue.
286 : */
287 : EQSERVER_API void removeOutputTileQueue(TileQueue* tileQueue);
288 :
289 : /** @return the vector of output tile queues. */
290 2480 : const TileQueues& getOutputTileQueues() const { return _outputTileQueues; }
291 : /** @return true if the compound is a tile compound. */
292 6 : bool hasTiles() const
293 : {
294 6 : return !_outputTileQueues.empty() || !_inputTileQueues.empty();
295 : }
296 : //@}
297 :
298 : /**
299 : * @name Inherit data access needed during channel update.
300 : *
301 : * Inherit data are the actual, as opposed to configured, attributes and
302 : * data used by the compound. The inherit data is updated at the
303 : * beginning of each update().
304 : */
305 : //@{
306 : RenderContext setupRenderContext(Eye eye) const;
307 4 : fabric::Frame::Buffer getInheritBuffers() const { return _inherit.buffers; }
308 8 : const PixelViewport& getInheritPixelViewport() const
309 : {
310 8 : return _inherit.pvp;
311 : }
312 : const Range& getInheritRange() const { return _inherit.range; }
313 32 : const Pixel& getInheritPixel() const { return _inherit.pixel; }
314 : const SubPixel& getInheritSubPixel() const { return _inherit.subPixel; }
315 8 : const Zoom& getInheritZoom() const { return _inherit.zoom; }
316 0 : uint32_t getInheritPeriod() const { return _inherit.period; }
317 : uint32_t getInheritPhase() const { return _inherit.phase; }
318 8 : float getInheritMaxFPS() const { return _inherit.maxFPS; }
319 24 : int32_t getInheritIAttribute(const IAttribute attr) const
320 : {
321 24 : return _inherit.iAttributes[attr];
322 : }
323 154 : uint32_t getInheritTasks() const { return _inherit.tasks; }
324 0 : uint32_t getInheritEyes() const { return _inherit.eyes; }
325 144 : Channel* getInheritChannel() { return _inherit.channel; }
326 84 : const Channel* getInheritChannel() const { return _inherit.channel; }
327 : /** @return true if the task is set, false if not. */
328 396 : bool testInheritTask(const fabric::Task task) const
329 : {
330 396 : return (_inherit.tasks & task);
331 : }
332 :
333 : /** Delete an inherit task, if it was set. */
334 52 : void unsetInheritTask(const fabric::Task task) { _inherit.tasks &= ~task; }
335 : /** @return true if the eye pass is actived, false if not. */
336 36 : bool testInheritEye(const Eye eye) const { return (_inherit.eyes & eye); }
337 : //@}
338 :
339 : /** @name Frustum Operations */
340 : //@{
341 : /**
342 : * Set the compound's frustum using a wall description.
343 : *
344 : * @param wall the wall description.
345 : */
346 : EQSERVER_API void setWall(const Wall& wall);
347 :
348 : /** @return the last specified wall description. */
349 28 : const Wall& getWall() const { return _frustum.getWall(); }
350 : /**
351 : * Set the compound's frustum using a projection description
352 : *
353 : * @param projection the projection description.
354 : */
355 : EQSERVER_API void setProjection(const Projection& projection);
356 :
357 : /** @return the last specified projection description. */
358 0 : const Projection& getProjection() const { return _frustum.getProjection(); }
359 : /** @return the type of the latest specified frustum. */
360 2304 : Frustum::Type getFrustumType() const { return _frustum.getCurrentType(); }
361 : /** @return the frustum of this compound. */
362 0 : Frustum& getFrustum() { return _frustum; }
363 : /** @return the frustum of this compound. */
364 : const Frustum& getFrustum() const { return _frustum; }
365 : /** Update the frustum from the view or segment. */
366 : void updateFrustum(const Vector3f& eye, const float ratio);
367 :
368 : /** compute the frustum for a given viewport */
369 : void computeTileFrustum(Frustumf& frustum, const fabric::Eye eye,
370 : Viewport vp, bool ortho) const;
371 :
372 : /** @return the bitwise OR of the eye values. */
373 2332 : uint32_t getEyes() const { return _data.eyes; }
374 : /**
375 : * Set the eyes to be used by the compound.
376 : *
377 : * Previously set eyes are overwritten.
378 : *
379 : * @param eyes the compound eyes.
380 : */
381 272 : void setEyes(const uint32_t eyes) { _data.eyes = eyes; }
382 : /**
383 : * Add eyes to be used by the compound.
384 : *
385 : * Previously set eyes are preserved.
386 : *
387 : * @param eyes the compound eyes.
388 : */
389 336 : void enableEye(const uint32_t eyes) { _data.eyes |= eyes; }
390 : //@}
391 :
392 : /** @name Compound Operations. */
393 : //@{
394 : /**
395 : * Traverse the compound and all children using a compound visitor.
396 : *
397 : * @param visitor the visitor.
398 : * @return the result of the visitor traversal.
399 : */
400 : EQSERVER_API VisitorResult accept(CompoundVisitor& visitor) const;
401 : /** Non-const version of accept(). */
402 : EQSERVER_API VisitorResult accept(CompoundVisitor& visitor);
403 :
404 : /** @internal Activate the given eyes for the the compound tree. */
405 : void activate(const uint32_t eyes);
406 :
407 : /** @internal Deactivate the given eyes for the the compound tree. */
408 : void deactivate(const uint32_t eyes);
409 :
410 : /**
411 : * @return if the compound is activated for selected eye
412 : and current (DPlex).
413 : *
414 : * @param eye eye which will be tested.
415 : */
416 : bool isInheritActive(const Eye eye) const;
417 :
418 : /** @return true if the compound is activated for any later eye pass. */
419 : bool isLastInheritEye(const Eye eye) const;
420 :
421 : /**
422 : * @return true if the compound is active and the compound's channel is
423 : * running.
424 : */
425 : bool isActive() const;
426 :
427 : /** Initialize this compound. */
428 : void init();
429 :
430 : /** Exit this compound. */
431 : void exit();
432 :
433 : /** Initialize the default tasks of this compound. */
434 : void updateInheritTasks();
435 :
436 : /** Register all distributed objects (frames) */
437 : void register_();
438 :
439 : /** Deregister all distributed objects (frames) */
440 : void deregister();
441 :
442 : /** Back up all relevant compound data. */
443 : void backup();
444 :
445 : /** Restore all relevant compound data. */
446 : void restore();
447 :
448 : /**
449 : * Updates this compound.
450 : *
451 : * The compound's parameters for the next frame are computed.
452 : */
453 : void update(const uint32_t frameNumber);
454 :
455 : /** Update the inherit data of this compound. */
456 : void updateInheritData(const uint32_t frameNumber);
457 : //@}
458 :
459 : /** @name Compound listener interface. */
460 : //@{
461 : /** Register a compound listener. */
462 : void addListener(CompoundListener* listener);
463 : /** Deregister a compound listener. */
464 : void removeListener(CompoundListener* listener);
465 :
466 : /** Notify all listeners that the compound is about to be updated. */
467 : void fireUpdatePre(const uint32_t frameNumber);
468 : //@}
469 :
470 : /**
471 : * @name Attributes
472 : */
473 : //@{
474 28 : void setIAttribute(const IAttribute attr, const int32_t value)
475 : {
476 28 : _data.iAttributes[attr] = value;
477 28 : }
478 11520 : int32_t getIAttribute(const IAttribute attr) const
479 : {
480 11520 : return _data.iAttributes[attr];
481 : }
482 : static const std::string& getIAttributeString(const IAttribute attr);
483 : //@}
484 :
485 : typedef std::unordered_map<std::string, co::Barrier*> BarrierMap;
486 : typedef BarrierMap::const_iterator BarrierMapCIter;
487 :
488 : typedef std::unordered_map<std::string, Frame*> FrameMap;
489 : typedef FrameMap::const_iterator FrameMapCIter;
490 :
491 : typedef std::unordered_map<std::string, TileQueue*> TileQueueMap;
492 :
493 : private:
494 : //-------------------- Members --------------------
495 : std::string _name;
496 :
497 : /**
498 : * The config the compound is attached to, only set on root
499 : * compounds.
500 : */
501 : friend class Config;
502 : Config* const _config;
503 :
504 : Compound* const _parent;
505 : Compounds _children;
506 :
507 : /** Percentage the resource should be used. */
508 : float _usage;
509 :
510 : /** Unique identifier for channel tasks. */
511 : uint32_t _taskID;
512 :
513 742 : struct Data
514 : {
515 : Data();
516 :
517 : Channel* channel;
518 : Viewport vp;
519 : PixelViewport pvp;
520 : Vector4i overdraw;
521 : Range range;
522 : Pixel pixel;
523 : SubPixel subPixel;
524 : FrustumData frustumData;
525 : Zoom zoom;
526 : fabric::Frame::Buffer buffers;
527 : uint32_t eyes;
528 : uint32_t tasks;
529 : uint32_t period;
530 : uint32_t phase;
531 : int32_t iAttributes[IATTR_ALL];
532 : float maxFPS;
533 :
534 : // compound activation per eye
535 : uint32_t active[fabric::NUM_EYES];
536 :
537 : union // placeholder for binary-compatible changes
538 : {
539 : char dummy[16];
540 : };
541 : };
542 :
543 : Data _data;
544 : Data _backup;
545 : Data _inherit;
546 :
547 : /** The frustum description of this compound. */
548 : Frustum _frustum;
549 :
550 : typedef std::vector<CompoundListener*> CompoundListeners;
551 : CompoundListeners _listeners;
552 :
553 : Equalizers _equalizers;
554 :
555 : SwapBarrierPtr _swapBarrier;
556 :
557 : Frames _inputFrames;
558 : Frames _outputFrames;
559 :
560 : TileQueues _inputTileQueues;
561 : TileQueues _outputTileQueues;
562 :
563 : struct Private;
564 : Private* _private; // placeholder for binary-compatible changes
565 :
566 8424 : LB_TS_VAR(_serverThread);
567 :
568 : //-------------------- Methods --------------------
569 : void _addChild(Compound* child);
570 : bool _removeChild(Compound* child);
571 :
572 : void _updateOverdraw(Wall& wall);
573 : void _updateInheritRoot();
574 : void _updateInheritNode();
575 : void _updateInheritPVP();
576 : void _updateInheritOverdraw();
577 : void _updateInheritStereo();
578 : void _updateInheritActive(const uint32_t frameNumber);
579 :
580 : void _setDefaultFrameName(Frame* frame);
581 : void _setDefaultTileQueueName(TileQueue* tileQueue);
582 :
583 : void _fireChildAdded(Compound* child);
584 : void _fireChildRemove(Compound* child);
585 :
586 : void _computeFrustum(RenderContext& context) const;
587 : void _computePerspective(RenderContext& context, const Vector3f& eye) const;
588 : void _computeOrtho(RenderContext& context, const Vector3f& eye) const;
589 : Vector3f _getEyePosition(const fabric::Eye eye) const;
590 : const Matrix4f& _getInverseHeadMatrix() const;
591 : void _computeFrustumCorners(Frustumf& frustum,
592 : const FrustumData& frustumData,
593 : const Vector3f& eye, const bool ortho,
594 : const Viewport* const vp = 0) const;
595 : };
596 :
597 : std::ostream& operator<<(std::ostream& os, const Compound& compound);
598 : }
599 : }
600 : #endif // EQSERVER_COMPOUND_H
|