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 : typedef fabric::Pipe<Node, Pipe, Window, PipeVisitor> Super;
40 : typedef co::CommandFunc<Pipe> PipeFunc;
41 :
42 1150 : Pipe::Pipe(Node* parent)
43 : : Super(parent)
44 : , _active(0)
45 : , _state(STATE_STOPPED)
46 1150 : , _lastDrawWindow(0)
47 : {
48 1150 : const Global* global = Global::instance();
49 3450 : for (unsigned i = 0; i < IATTR_LAST; ++i)
50 : {
51 2300 : const IAttribute attr = static_cast<IAttribute>(i);
52 2300 : setIAttribute(attr, global->getPipeIAttribute(attr));
53 : }
54 1150 : }
55 :
56 2296 : Pipe::~Pipe()
57 : {
58 2296 : }
59 :
60 4 : void Pipe::attach(const uint128_t& id, const uint32_t instanceID)
61 : {
62 4 : Super::attach(id, instanceID);
63 :
64 4 : co::CommandQueue* cmdQ = getCommandThreadQueue();
65 8 : registerCommand(fabric::CMD_OBJECT_SYNC, PipeFunc(this, &Pipe::_cmdSync),
66 4 : cmdQ);
67 4 : registerCommand(fabric::CMD_PIPE_CONFIG_INIT_REPLY,
68 8 : PipeFunc(this, &Pipe::_cmdConfigInitReply), cmdQ);
69 4 : registerCommand(fabric::CMD_PIPE_CONFIG_EXIT_REPLY,
70 8 : PipeFunc(this, &Pipe::_cmdConfigExitReply), cmdQ);
71 4 : }
72 :
73 0 : void Pipe::removeChild(const uint128_t& id)
74 : {
75 0 : LBASSERT(getConfig()->isRunning());
76 :
77 0 : Window* window = _findWindow(id);
78 0 : LBASSERT(window);
79 0 : if (window)
80 0 : window->postDelete();
81 0 : }
82 :
83 26 : ServerPtr Pipe::getServer()
84 : {
85 26 : Node* node = getNode();
86 26 : LBASSERT(node);
87 26 : return (node ? node->getServer() : 0);
88 : }
89 :
90 0 : ConstServerPtr Pipe::getServer() const
91 : {
92 0 : const Node* node = getNode();
93 0 : LBASSERT(node);
94 0 : return node ? node->getServer() : 0;
95 : }
96 :
97 618 : Config* Pipe::getConfig()
98 : {
99 618 : Node* node = getNode();
100 618 : LBASSERT(node);
101 618 : return (node ? node->getConfig() : 0);
102 : }
103 :
104 4 : const Config* Pipe::getConfig() const
105 : {
106 4 : const Node* node = getNode();
107 4 : LBASSERT(node);
108 4 : return (node ? node->getConfig() : 0);
109 : }
110 :
111 22 : co::CommandQueue* Pipe::getMainThreadQueue()
112 : {
113 22 : Node* node = getNode();
114 22 : LBASSERT(node);
115 22 : return node->getMainThreadQueue();
116 : }
117 :
118 26 : co::CommandQueue* Pipe::getCommandThreadQueue()
119 : {
120 26 : Node* node = getNode();
121 26 : LBASSERT(node);
122 26 : return node->getCommandThreadQueue();
123 : }
124 :
125 2 : Channel* Pipe::getChannel(const ChannelPath& path)
126 : {
127 2 : const Windows& windows = getWindows();
128 2 : LBASSERTINFO(windows.size() > path.windowIndex, "Path " << path << " for "
129 : << *this);
130 :
131 2 : if (windows.size() <= path.windowIndex)
132 0 : return 0;
133 :
134 2 : return windows[path.windowIndex]->getChannel(path);
135 : }
136 :
137 8 : void Pipe::activate()
138 : {
139 8 : Node* node = getNode();
140 8 : LBASSERT(node);
141 :
142 8 : ++_active;
143 8 : if (node)
144 8 : node->activate();
145 :
146 8 : LBLOG(LOG_VIEW) << "activate: " << _active << std::endl;
147 8 : }
148 :
149 8 : void Pipe::deactivate()
150 : {
151 8 : LBASSERT(_active != 0);
152 :
153 8 : Node* node = getNode();
154 8 : LBASSERT(node);
155 :
156 8 : --_active;
157 8 : if (node)
158 8 : node->deactivate();
159 :
160 8 : LBLOG(LOG_VIEW) << "deactivate: " << _active << std::endl;
161 8 : };
162 :
163 126 : void Pipe::addTasks(const uint32_t tasks)
164 : {
165 126 : Node* node = getNode();
166 126 : LBASSERT(node);
167 126 : setTasks(getTasks() | tasks);
168 126 : node->addTasks(tasks);
169 126 : }
170 :
171 24 : co::ObjectOCommand Pipe::send(const uint32_t cmd)
172 : {
173 24 : return getNode()->send(cmd, getID());
174 : }
175 :
176 : //===========================================================================
177 : // Operations
178 : //===========================================================================
179 :
180 : //---------------------------------------------------------------------------
181 : // init
182 : //---------------------------------------------------------------------------
183 4 : void Pipe::configInit(const uint128_t& initID, const uint32_t frameNumber)
184 : {
185 4 : LBASSERT(_state == STATE_STOPPED);
186 4 : _state = STATE_INITIALIZING;
187 :
188 4 : LBLOG(LOG_INIT) << "Create pipe" << std::endl;
189 8 : getNode()->send(fabric::CMD_NODE_CREATE_PIPE, getNode()->getID())
190 12 : << getID() << isThreaded();
191 :
192 4 : LBLOG(LOG_INIT) << "Init pipe" << std::endl;
193 4 : send(fabric::CMD_PIPE_CONFIG_INIT) << initID << frameNumber;
194 4 : }
195 :
196 4 : bool Pipe::syncConfigInit()
197 : {
198 4 : LBASSERT(_state == STATE_INITIALIZING || _state == STATE_INIT_SUCCESS ||
199 : _state == STATE_INIT_FAILED);
200 :
201 4 : _state.waitNE(STATE_INITIALIZING);
202 :
203 4 : if (_state == STATE_INIT_SUCCESS)
204 : {
205 4 : _state = STATE_RUNNING;
206 4 : return true;
207 : }
208 :
209 0 : LBWARN << "Pipe initialization failed" << std::endl;
210 0 : configExit();
211 0 : return false;
212 : }
213 :
214 : //---------------------------------------------------------------------------
215 : // exit
216 : //---------------------------------------------------------------------------
217 4 : void Pipe::configExit()
218 : {
219 4 : if (_state == STATE_EXITING)
220 0 : return;
221 :
222 4 : LBASSERT(_state == STATE_RUNNING || _state == STATE_INIT_FAILED);
223 4 : _state = STATE_EXITING;
224 :
225 4 : LBLOG(LOG_INIT) << "Exit pipe" << std::endl;
226 4 : send(fabric::CMD_PIPE_CONFIG_EXIT);
227 : }
228 :
229 4 : bool Pipe::syncConfigExit()
230 : {
231 4 : LBASSERT(_state == STATE_EXITING || _state == STATE_EXIT_SUCCESS ||
232 : _state == STATE_EXIT_FAILED);
233 :
234 4 : _state.waitNE(STATE_EXITING);
235 4 : const bool success = (_state == STATE_EXIT_SUCCESS);
236 4 : LBASSERT(success || _state == STATE_EXIT_FAILED);
237 :
238 4 : _state = isActive() ? STATE_FAILED : STATE_STOPPED;
239 4 : setTasks(fabric::TASK_NONE);
240 4 : return success;
241 : }
242 :
243 : //---------------------------------------------------------------------------
244 : // update
245 : //---------------------------------------------------------------------------
246 4 : void Pipe::update(const uint128_t& frameID, const uint32_t frameNumber)
247 : {
248 4 : if (!isRunning())
249 0 : return;
250 :
251 4 : LBASSERT(isActive())
252 4 : send(fabric::CMD_PIPE_FRAME_START_CLOCK);
253 :
254 8 : send(fabric::CMD_PIPE_FRAME_START) << getVersion() << frameID
255 4 : << frameNumber;
256 4 : LBLOG(LOG_TASKS) << "TASK pipe start frame " << frameNumber << " id "
257 4 : << frameID << std::endl;
258 :
259 4 : const Windows& windows = getWindows();
260 8 : for (Windows::const_iterator i = windows.begin(); i != windows.end(); ++i)
261 4 : (*i)->updateDraw(frameID, frameNumber);
262 :
263 8 : for (Windows::const_iterator i = windows.begin(); i != windows.end(); ++i)
264 4 : (*i)->updatePost(frameID, frameNumber);
265 :
266 4 : if (!_lastDrawWindow) // no FrameDrawFinish sent
267 : {
268 0 : send(fabric::CMD_PIPE_FRAME_DRAW_FINISH) << frameID << frameNumber;
269 0 : LBLOG(LOG_TASKS) << "TASK pipe draw finish " << getName() << " frame "
270 0 : << frameNumber << " id " << frameID << std::endl;
271 : }
272 4 : _lastDrawWindow = 0;
273 :
274 4 : send(fabric::CMD_PIPE_FRAME_FINISH) << frameID << frameNumber;
275 :
276 4 : LBLOG(LOG_TASKS) << "TASK pipe finish frame " << frameNumber << " id "
277 4 : << frameID << std::endl;
278 : }
279 :
280 : //===========================================================================
281 : // command handling
282 : //===========================================================================
283 4 : bool Pipe::_cmdConfigInitReply(co::ICommand& cmd)
284 : {
285 8 : co::ObjectICommand command(cmd);
286 4 : const bool result = command.read<bool>();
287 :
288 4 : LBVERB << "handle pipe configInit reply " << command << " result " << result
289 4 : << std::endl;
290 :
291 4 : _state = result ? STATE_INIT_SUCCESS : STATE_INIT_FAILED;
292 8 : return true;
293 : }
294 :
295 4 : bool Pipe::_cmdConfigExitReply(co::ICommand& cmd)
296 : {
297 8 : co::ObjectICommand command(cmd);
298 4 : LBVERB << "handle pipe configExit reply " << command << std::endl;
299 :
300 4 : _state = command.read<bool>() ? STATE_EXIT_SUCCESS : STATE_EXIT_FAILED;
301 8 : return true;
302 : }
303 :
304 580 : void Pipe::output(std::ostream& os) const
305 : {
306 580 : bool attrPrinted = false;
307 1740 : for (IAttribute i = static_cast<IAttribute>(0); i < IATTR_LAST;
308 1160 : i = static_cast<IAttribute>(static_cast<uint32_t>(i) + 1))
309 : {
310 1160 : const int value = getIAttribute(i);
311 1160 : if (value == Global::instance()->getPipeIAttribute(i))
312 1150 : continue;
313 :
314 10 : if (!attrPrinted)
315 : {
316 10 : os << std::endl << "attributes" << std::endl;
317 10 : os << "{" << std::endl << lunchbox::indent;
318 10 : attrPrinted = true;
319 : }
320 :
321 : os << (i == IATTR_HINT_THREAD
322 : ? "hint_thread "
323 10 : : i == IATTR_HINT_AFFINITY ? "hint_affinity " : "ERROR")
324 10 : << static_cast<fabric::IAttribute>(value) << std::endl;
325 : }
326 :
327 580 : if (attrPrinted)
328 10 : os << lunchbox::exdent << "}" << std::endl;
329 580 : }
330 : }
331 : }
332 :
333 : #include "../fabric/pipe.ipp"
334 : template class eq::fabric::Pipe<eq::server::Node, eq::server::Pipe,
335 : eq::server::Window, eq::server::PipeVisitor>;
336 :
337 : /** @cond IGNORE */
338 : template std::ostream& eq::fabric::operator<<(std::ostream&,
339 60 : const eq::server::Super&);
340 : /** @endcond */
|