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 <eq/fabric/pipe.h> // base class
29 : #include <co/objectVersion.h>
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,
125 : const Eye eye, 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 : /**
170 : * Process a received event.
171 : *
172 : * The task of this method is to update the node as necessary, and transform
173 : * the event into a config event to be send to the application using
174 : * Config::sendEvent().
175 : *
176 : * @param event the received event.
177 : * @return true when the event was handled, false if not.
178 : * @version 1.5.2
179 : */
180 : EQ_API virtual bool processEvent( const Event& event );
181 :
182 : /** @internal Start the pipe thread. */
183 : void startThread();
184 :
185 : /** @internal Trigger pipe thread exit and wait for completion. */
186 : void exitThread();
187 :
188 : void cancelThread(); //!< @internal
189 :
190 : /** @internal Start the async readback thread. */
191 : bool startTransferThread();
192 :
193 : /** @internal @return the qthread, or nullptr. */
194 : QThread* getTransferQThread();
195 :
196 : /** @internal Checks if async readback thread is running. */
197 : bool hasTransferThread() const;
198 :
199 : /**
200 : * @name Interface to and from the SystemPipe, the window-system
201 : * specific pieces for a pipe.
202 : */
203 : //@{
204 : /**
205 : * Set the system-specific pipe implementation.
206 : *
207 : * The system-specific pipe implements the window-system-dependent part.
208 : * The os-specific pipe has to be initialized.
209 : * @version 1.0
210 : */
211 : EQ_API void setSystemPipe( SystemPipe* pipe );
212 :
213 : /** @return the OS-specific pipe implementation. @version 1.0 */
214 : EQ_API SystemPipe* getSystemPipe();
215 :
216 : /** @return the OS-specific pipe implementation. @version 1.0 */
217 : EQ_API const SystemPipe* getSystemPipe() const;
218 : //@}
219 :
220 : /** @name Configuration. */
221 : //@{
222 : /**
223 : * Create a new MessagePump for this pipe.
224 : *
225 : * At most one message pump per execution thread is created. Each pipe
226 : * render thread creates one message pump for its window system. The process
227 : * main thread creates a message pump for AGL pipes and non-threaded
228 : * pipes. Applications which do their own message pumping outside of
229 : * Equalizer should return 0 here.
230 : *
231 : * @return the message pump, or 0.
232 : * @version 1.0
233 : */
234 : EQ_API virtual MessagePump* createMessagePump();
235 :
236 : /** @return the pipe's message pump, or 0. @version 1.0 */
237 : MessagePump* getMessagePump();
238 : //@}
239 :
240 : /** @internal @sa Serializable::setDirty() */
241 : EQ_API virtual void setDirty( const uint64_t bits );
242 :
243 : protected:
244 : /** @name Information queries */
245 : //@{
246 : /**
247 : * @return true if this pipe can use the requested window system given its
248 : * port and device.
249 : * @version 1.11
250 : */
251 : EQ_API bool isWindowSystemAvailable( const std::string& name ) const;
252 : //@}
253 :
254 : /** @name Operations */
255 : //@{
256 : /**
257 : * Start a frame by unlocking all child resources.
258 : *
259 : * @param frameNumber the frame to start.
260 : * @version 1.0
261 : */
262 : EQ_API void startFrame( const uint32_t frameNumber );
263 :
264 : /**
265 : * Signal the completion of a frame to the parent.
266 : *
267 : * @param frameNumber the frame to end.
268 : * @version 1.0
269 : */
270 : EQ_API void releaseFrame( const uint32_t frameNumber );
271 :
272 : /**
273 : * Release the local synchronization of the parent for a frame.
274 : *
275 : * @param frameNumber the frame to release.
276 : * @version 1.0
277 : */
278 : EQ_API void releaseFrameLocal( const uint32_t frameNumber );
279 : //@}
280 :
281 : /**
282 : * @name Callbacks
283 : *
284 : * The callbacks are called by Equalizer during rendering to execute
285 : * various actions.
286 : */
287 : //@{
288 : /**
289 : * Choose the window system to be used by this pipe.
290 : *
291 : * This function determines which of the supported windowing systems is used
292 : * by this pipe instance.
293 : *
294 : * @return the window system currently used by this pipe.
295 : * @version 1.0
296 : */
297 : EQ_API virtual WindowSystem selectWindowSystem() const;
298 :
299 : /**
300 : * Initialize this pipe.
301 : *
302 : * @param initID the init identifier.
303 : * @version 1.0
304 : */
305 : EQ_API virtual bool configInit( const uint128_t& initID );
306 :
307 : /**
308 : * Initialize the OS-specific pipe.
309 : *
310 : * @sa setSystemPipe()
311 : * @version 1.0
312 : */
313 : EQ_API virtual bool configInitSystemPipe( const uint128_t& initID );
314 :
315 : /**
316 : * De-initialize this pipe.
317 : * @version 1.0
318 : */
319 : EQ_API virtual bool configExit();
320 :
321 : /**
322 : * Start rendering a frame.
323 : *
324 : * Called once at the beginning of each frame, to do per-frame updates of
325 : * pipe-specific data, for example updating the rendering engine. Waits for
326 : * the node to start the frame, unless the thread model is async. If the
327 : * thread model is async, the local synchronization is released immediately.
328 : *
329 : * This method has to call startFrame().
330 : *
331 : * @param frameID the per-frame identifier.
332 : * @param frameNumber the frame to start.
333 : * @sa Config::startFrame(), Node::startFrame(),
334 : * Node::waitFrameStarted()
335 : * @version 1.0
336 : */
337 : EQ_API virtual void frameStart( const uint128_t& frameID,
338 : const uint32_t frameNumber );
339 :
340 : /**
341 : * Finish rendering a frame.
342 : *
343 : * Called once at the end of each frame, to do per-frame updates of
344 : * pipe-specific data, for example updating the rendering engine. Releases
345 : * the local synchronization if the thread model is local_sync. Always
346 : * releases the global synchronization for this pipe.
347 : *
348 : * This method has to call releaseFrame().
349 : *
350 : * @param frameID the per-frame identifier.
351 : * @param frameNumber the frame to finish.
352 : * @version 1.0
353 : */
354 : EQ_API virtual void frameFinish( const uint128_t& frameID,
355 : const uint32_t frameNumber );
356 :
357 : /**
358 : * Finish drawing.
359 : *
360 : * Called once per frame after the last draw operation. Releases the local
361 : * synchronization if the thread model is draw_sync (the default).
362 : *
363 : * @param frameID the per-frame identifier.
364 : * @param frameNumber the frame to finished with draw.
365 : * @version 1.0
366 : */
367 : EQ_API virtual void frameDrawFinish( const uint128_t& frameID,
368 : const uint32_t frameNumber );
369 :
370 : /** @internal */
371 : EQ_API virtual void attach( const uint128_t& id, const uint32_t instanceID );
372 :
373 : private:
374 : detail::Pipe* const _impl;
375 : friend class detail::RenderThread;
376 :
377 : //-------------------- Methods --------------------
378 : void _setupCommandQueue();
379 : void _setupAffinity();
380 : void _exitCommandQueue();
381 :
382 : /** @internal @return lunchbox::Thread::Affinity mask for this GPU. */
383 : EQ_API int32_t _getAutoAffinity() const;
384 : friend class detail::ThreadAffinityVisitor;
385 :
386 : //friend class Window;
387 :
388 : void _stopTransferThread();
389 :
390 : /** @internal Release the views not used for some revisions. */
391 : void _releaseViews();
392 :
393 : /** @internal Clear the view cache and release all views. */
394 : void _flushViews();
395 :
396 : /** @internal Clear the queue cache and release all queues. */
397 : void _flushQueues();
398 :
399 : /* The command functions. */
400 : bool _cmdCreateWindow( co::ICommand& command );
401 : bool _cmdDestroyWindow( co::ICommand& command );
402 : bool _cmdConfigInit( co::ICommand& command );
403 : bool _cmdConfigExit( co::ICommand& command );
404 : bool _cmdFrameStartClock( co::ICommand& command );
405 : bool _cmdFrameStart( co::ICommand& command );
406 : bool _cmdFrameFinish( co::ICommand& command );
407 : bool _cmdFrameDrawFinish( co::ICommand& command );
408 : bool _cmdExitThread( co::ICommand& command );
409 : bool _cmdDetachView( co::ICommand& command );
410 : bool _cmdExitTransferThread( co::ICommand& command );
411 :
412 92 : LB_TS_VAR( _pipeThread );
413 : };
414 : }
415 :
416 : #endif // EQ_PIPE_H
|