Line data Source code
1 :
2 : /* Copyright (c) 2005-2015, 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_PIPE_H
21 : #define EQ_PIPE_H
22 :
23 : #include <eq/api.h>
24 : #include <eq/eye.h> // Eye enum
25 : #include <eq/types.h>
26 : #include <eq/visitorResult.h> // enum
27 :
28 : #include <co/objectVersion.h>
29 : #include <eq/fabric/pipe.h> // base class
30 :
31 : namespace eq
32 : {
33 : namespace detail
34 : {
35 : class Pipe;
36 : class RenderThread;
37 : class ThreadAffinityVisitor;
38 : }
39 :
40 : /**
41 : * A Pipe represents a graphics card (GPU) on a Node.
42 : *
43 : * All Pipe, Window and Channel task methods are executed in a separate
44 : * co::Worker thread, in parallel with all other pipes in the system. An
45 : * exception are non-threaded pipes, which execute their tasks on the Node's
46 : * main thread.
47 : *
48 : * @sa fabric::Pipe
49 : */
50 : class Pipe : public fabric::Pipe<Node, Pipe, eq::Window, PipeVisitor>
51 : {
52 : public:
53 : /** Construct a new pipe. @version 1.0 */
54 : EQ_API explicit Pipe(Node* parent);
55 :
56 : /** Destruct the pipe. @version 1.0 */
57 : EQ_API virtual ~Pipe();
58 :
59 : /** @name Data Access. */
60 : //@{
61 : EQ_API co::CommandQueue* getPipeThreadQueue(); //!< @internal
62 : co::CommandQueue* getMainThreadQueue(); //!< @internal
63 : co::CommandQueue* getCommandThreadQueue(); //!< @internal
64 : co::CommandQueue* getTransferThreadQueue(); //!< @internal
65 :
66 : /** @return the parent configuration. @version 1.0 */
67 : EQ_API Config* getConfig();
68 : /** @return the parent configuration. @version 1.0 */
69 : EQ_API const Config* getConfig() const;
70 :
71 : /** @return the parent client node. @version 1.0 */
72 : EQ_API ClientPtr getClient();
73 :
74 : /** @return the parent server node. @version 1.0 */
75 : EQ_API ServerPtr getServer();
76 :
77 : /**
78 : * @return true if this pipe is running, false otherwise.
79 : * @version 1.0
80 : */
81 : bool isRunning() const;
82 :
83 : /**
84 : * @return true if this pipe is stopped, false otherwise.
85 : * @version 1.0
86 : */
87 : EQ_API bool isStopped() const;
88 :
89 : /**
90 : * Return the current frame number.
91 : *
92 : * To be called only from the pipe thread. Updated by startFrame().
93 : * @return the current frame number.
94 : * @version 1.0
95 : */
96 : EQ_API uint32_t getCurrentFrame() const;
97 : EQ_API uint32_t getFinishedFrame() const; //!< @internal
98 :
99 : /**
100 : * Return the window system used by this pipe.
101 : *
102 : * The return value is quaranteed to be constant for an initialized pipe,
103 : * that is, the window system is determined using selectWindowSystem()
104 : * before configInit() is executed.
105 : *
106 : * @return the window system used by this pipe.
107 : * @version 1.0
108 : */
109 : EQ_API WindowSystem getWindowSystem() const;
110 : //@}
111 :
112 : /**
113 : * @name Operations
114 : */
115 : //@{
116 : /** @internal
117 : * Get an assembly frame.
118 : *
119 : * @param frameVersion the frame's identifier and version.
120 : * @param eye the current eye pass.
121 : * @param output true if an output frame, false if input frame
122 : * @return the frame.
123 : */
124 : Frame* getFrame(const co::ObjectVersion& frameVersion, const Eye eye,
125 : const bool output);
126 :
127 : /** @internal @return the queue for the given identifier and version. */
128 : co::QueueSlave* getQueue(const uint128_t& queueID);
129 :
130 : /** @internal Clear the frame cache and delete all frames. */
131 : void flushFrames(util::ObjectManager& om);
132 :
133 : /** @internal @return the view for the given identifier and version. */
134 : const View* getView(const co::ObjectVersion& viewVersion) const;
135 :
136 : /** @internal @return the view for the given identifier and version. */
137 : View* getView(const co::ObjectVersion& viewVersion);
138 : //@}
139 :
140 : void waitExited() const; //!< @internal Wait for the pipe to be exited
141 : void notifyMapped(); //!< @internal
142 :
143 : /**
144 : * @internal
145 : * Wait for a frame to be finished.
146 : *
147 : * @param frameNumber the frame number.
148 : * @sa releaseFrame()
149 : */
150 : EQ_API void waitFrameFinished(const uint32_t frameNumber);
151 :
152 : /**
153 : * Send a pipe error event to the application node.
154 : *
155 : * @param error the error code.
156 : * @version 1.7.1
157 : */
158 : EQ_API EventOCommand sendError(const uint32_t error);
159 :
160 : /**
161 : * @internal
162 : * Wait for a frame to be released locally.
163 : *
164 : * @param frameNumber the frame number.
165 : * @sa releaseFrameLocal()
166 : */
167 : EQ_API void waitFrameLocal(const uint32_t frameNumber) const;
168 :
169 : EQ_API bool processEvent(Statistic& event);
170 :
171 : /** @internal Start the pipe thread. */
172 : void startThread();
173 :
174 : /** @internal Trigger pipe thread exit and wait for completion. */
175 : void exitThread();
176 :
177 : void cancelThread(); //!< @internal
178 :
179 : /** @internal Start the async readback thread. */
180 : bool startTransferThread();
181 :
182 : /** @internal @return the qthread, or nullptr. */
183 : QThread* getTransferQThread();
184 :
185 : /** @internal Checks if async readback thread is running. */
186 : bool hasTransferThread() const;
187 :
188 : /**
189 : * @name Interface to and from the SystemPipe, the window-system
190 : * specific pieces for a pipe.
191 : */
192 : //@{
193 : /**
194 : * Set the system-specific pipe implementation.
195 : *
196 : * The system-specific pipe implements the window-system-dependent part.
197 : * The os-specific pipe has to be initialized.
198 : * @version 1.0
199 : */
200 : EQ_API void setSystemPipe(SystemPipe* pipe);
201 :
202 : /** @return the OS-specific pipe implementation. @version 1.0 */
203 : EQ_API SystemPipe* getSystemPipe();
204 :
205 : /** @return the OS-specific pipe implementation. @version 1.0 */
206 : EQ_API const SystemPipe* getSystemPipe() const;
207 : //@}
208 :
209 : /** @name Configuration. */
210 : //@{
211 : /**
212 : * Create a new MessagePump for this pipe.
213 : *
214 : * At most one message pump per execution thread is created. Each pipe
215 : * render thread creates one message pump for its window system. The process
216 : * main thread creates a message pump for AGL pipes and non-threaded
217 : * pipes. Applications which do their own message pumping outside of
218 : * Equalizer should return 0 here.
219 : *
220 : * @return the message pump, or 0.
221 : * @version 1.0
222 : */
223 : EQ_API virtual MessagePump* createMessagePump();
224 :
225 : /** @return the pipe's message pump, or 0. @version 1.0 */
226 : MessagePump* getMessagePump();
227 : //@}
228 :
229 : /** @internal @sa Serializable::setDirty() */
230 : EQ_API virtual void setDirty(const uint64_t bits);
231 :
232 : protected:
233 : /** @name Information queries */
234 : //@{
235 : /**
236 : * @return true if this pipe can use the requested window system given its
237 : * port and device.
238 : * @version 1.11
239 : */
240 : EQ_API bool isWindowSystemAvailable(const std::string& name) const;
241 : //@}
242 :
243 : /** @name Operations */
244 : //@{
245 : /**
246 : * Start a frame by unlocking all child resources.
247 : *
248 : * @param frameNumber the frame to start.
249 : * @version 1.0
250 : */
251 : EQ_API void startFrame(const uint32_t frameNumber);
252 :
253 : /**
254 : * Signal the completion of a frame to the parent.
255 : *
256 : * @param frameNumber the frame to end.
257 : * @version 1.0
258 : */
259 : EQ_API void releaseFrame(const uint32_t frameNumber);
260 :
261 : /**
262 : * Release the local synchronization of the parent for a frame.
263 : *
264 : * @param frameNumber the frame to release.
265 : * @version 1.0
266 : */
267 : EQ_API void releaseFrameLocal(const uint32_t frameNumber);
268 : //@}
269 :
270 : /**
271 : * @name Callbacks
272 : *
273 : * The callbacks are called by Equalizer during rendering to execute
274 : * various actions.
275 : */
276 : //@{
277 : /**
278 : * Choose the window system to be used by this pipe.
279 : *
280 : * This function determines which of the supported windowing systems is used
281 : * by this pipe instance.
282 : *
283 : * @return the window system currently used by this pipe.
284 : * @version 1.0
285 : */
286 : EQ_API virtual WindowSystem selectWindowSystem() const;
287 :
288 : /**
289 : * Initialize this pipe.
290 : *
291 : * @param initID the init identifier.
292 : * @version 1.0
293 : */
294 : EQ_API virtual bool configInit(const uint128_t& initID);
295 :
296 : /**
297 : * Initialize the OS-specific pipe.
298 : *
299 : * @sa setSystemPipe()
300 : * @version 1.0
301 : */
302 : EQ_API virtual bool configInitSystemPipe(const uint128_t& initID);
303 :
304 : /**
305 : * De-initialize this pipe.
306 : * @version 1.0
307 : */
308 : EQ_API virtual bool configExit();
309 :
310 : /**
311 : * Start rendering a frame.
312 : *
313 : * Called once at the beginning of each frame, to do per-frame updates of
314 : * pipe-specific data, for example updating the rendering engine. Waits for
315 : * the node to start the frame, unless the thread model is async. If the
316 : * thread model is async, the local synchronization is released immediately.
317 : *
318 : * This method has to call startFrame().
319 : *
320 : * @param frameID the per-frame identifier.
321 : * @param frameNumber the frame to start.
322 : * @sa Config::startFrame(), Node::startFrame(),
323 : * Node::waitFrameStarted()
324 : * @version 1.0
325 : */
326 : EQ_API virtual void frameStart(const uint128_t& frameID,
327 : const uint32_t frameNumber);
328 :
329 : /**
330 : * Finish rendering a frame.
331 : *
332 : * Called once at the end of each frame, to do per-frame updates of
333 : * pipe-specific data, for example updating the rendering engine. Releases
334 : * the local synchronization if the thread model is local_sync. Always
335 : * releases the global synchronization for this pipe.
336 : *
337 : * This method has to call releaseFrame().
338 : *
339 : * @param frameID the per-frame identifier.
340 : * @param frameNumber the frame to finish.
341 : * @version 1.0
342 : */
343 : EQ_API virtual void frameFinish(const uint128_t& frameID,
344 : const uint32_t frameNumber);
345 :
346 : /**
347 : * Finish drawing.
348 : *
349 : * Called once per frame after the last draw operation. Releases the local
350 : * synchronization if the thread model is draw_sync (the default).
351 : *
352 : * @param frameID the per-frame identifier.
353 : * @param frameNumber the frame to finished with draw.
354 : * @version 1.0
355 : */
356 : EQ_API virtual void frameDrawFinish(const uint128_t& frameID,
357 : const uint32_t frameNumber);
358 :
359 : /** @internal */
360 : EQ_API virtual void attach(const uint128_t& id, const uint32_t instanceID);
361 :
362 : private:
363 : detail::Pipe* const _impl;
364 : friend class detail::RenderThread;
365 :
366 : //-------------------- Methods --------------------
367 : void _setupCommandQueue();
368 : void _setupAffinity();
369 : void _exitCommandQueue();
370 :
371 : /** @internal @return lunchbox::Thread::Affinity mask for this GPU. */
372 : EQ_API int32_t _getAutoAffinity() const;
373 : friend class detail::ThreadAffinityVisitor;
374 :
375 : // friend class Window;
376 :
377 : void _stopTransferThread();
378 :
379 : /** @internal Release the views not used for some revisions. */
380 : void _releaseViews();
381 :
382 : /** @internal Clear the view cache and release all views. */
383 : void _flushViews();
384 :
385 : /** @internal Clear the queue cache and release all queues. */
386 : void _flushQueues();
387 :
388 : /* The command functions. */
389 : bool _cmdCreateWindow(co::ICommand& command);
390 : bool _cmdDestroyWindow(co::ICommand& command);
391 : bool _cmdConfigInit(co::ICommand& command);
392 : bool _cmdConfigExit(co::ICommand& command);
393 : bool _cmdFrameStartClock(co::ICommand& command);
394 : bool _cmdFrameStart(co::ICommand& command);
395 : bool _cmdFrameFinish(co::ICommand& command);
396 : bool _cmdFrameDrawFinish(co::ICommand& command);
397 : bool _cmdExitThread(co::ICommand& command);
398 : bool _cmdDetachView(co::ICommand& command);
399 : bool _cmdExitTransferThread(co::ICommand& command);
400 :
401 4 : LB_TS_VAR(_pipeThread);
402 : };
403 : }
404 :
405 : #endif // EQ_PIPE_H
|