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 : /**
221 : * @name Interface to and from the ComputeContext
222 : * @warning experimental - may not be supported in the future.
223 : */
224 : //@{
225 : /** Set the compute-specific context. */
226 : EQ_API void setComputeContext( ComputeContext* ctx );
227 :
228 : /** @return the compute context. */
229 : EQ_API const ComputeContext* getComputeContext() const;
230 :
231 : /** @return the compute context. */
232 : EQ_API ComputeContext* getComputeContext();
233 : //@}
234 :
235 : /** @name Configuration. */
236 : //@{
237 : /**
238 : * Create a new MessagePump for this pipe.
239 : *
240 : * At most one message pump per execution thread is created. Each pipe
241 : * render thread creates one message pump for its window system. The process
242 : * main thread creates a message pump for AGL pipes and non-threaded
243 : * pipes. Applications which do their own message pumping outside of
244 : * Equalizer should return 0 here.
245 : *
246 : * @return the message pump, or 0.
247 : * @version 1.0
248 : */
249 : EQ_API virtual MessagePump* createMessagePump();
250 :
251 : /** @return the pipe's message pump, or 0. @version 1.0 */
252 : MessagePump* getMessagePump();
253 : //@}
254 :
255 : /** @internal @sa Serializable::setDirty() */
256 : EQ_API virtual void setDirty( const uint64_t bits );
257 :
258 : protected:
259 : /** @name Information queries */
260 : //@{
261 : /**
262 : * @return true if this pipe can use the requested window system given its
263 : * port and device.
264 : * @version 1.11
265 : */
266 : EQ_API bool isWindowSystemAvailable( const std::string& name ) const;
267 : //@}
268 :
269 : /** @name Operations */
270 : //@{
271 : /**
272 : * Start a frame by unlocking all child resources.
273 : *
274 : * @param frameNumber the frame to start.
275 : * @version 1.0
276 : */
277 : EQ_API void startFrame( const uint32_t frameNumber );
278 :
279 : /**
280 : * Signal the completion of a frame to the parent.
281 : *
282 : * @param frameNumber the frame to end.
283 : * @version 1.0
284 : */
285 : EQ_API void releaseFrame( const uint32_t frameNumber );
286 :
287 : /**
288 : * Release the local synchronization of the parent for a frame.
289 : *
290 : * @param frameNumber the frame to release.
291 : * @version 1.0
292 : */
293 : EQ_API void releaseFrameLocal( const uint32_t frameNumber );
294 : //@}
295 :
296 : /**
297 : * @name Callbacks
298 : *
299 : * The callbacks are called by Equalizer during rendering to execute
300 : * various actions.
301 : */
302 : //@{
303 : /**
304 : * Choose the window system to be used by this pipe.
305 : *
306 : * This function determines which of the supported windowing systems is used
307 : * by this pipe instance.
308 : *
309 : * @return the window system currently used by this pipe.
310 : * @version 1.0
311 : */
312 : EQ_API virtual WindowSystem selectWindowSystem() const;
313 :
314 : /**
315 : * Initialize this pipe.
316 : *
317 : * @param initID the init identifier.
318 : * @version 1.0
319 : */
320 : EQ_API virtual bool configInit( const uint128_t& initID );
321 :
322 : /**
323 : * Initialize the OS-specific pipe.
324 : *
325 : * @sa setSystemPipe()
326 : * @version 1.0
327 : */
328 : EQ_API virtual bool configInitSystemPipe( const uint128_t& initID );
329 :
330 : /**
331 : * De-initialize this pipe.
332 : * @version 1.0
333 : */
334 : EQ_API virtual bool configExit();
335 :
336 : /**
337 : * Start rendering a frame.
338 : *
339 : * Called once at the beginning of each frame, to do per-frame updates of
340 : * pipe-specific data, for example updating the rendering engine. Waits for
341 : * the node to start the frame, unless the thread model is async. If the
342 : * thread model is async, the local synchronization is released immediately.
343 : *
344 : * This method has to call startFrame().
345 : *
346 : * @param frameID the per-frame identifier.
347 : * @param frameNumber the frame to start.
348 : * @sa Config::startFrame(), Node::startFrame(),
349 : * Node::waitFrameStarted()
350 : * @version 1.0
351 : */
352 : EQ_API virtual void frameStart( const uint128_t& frameID,
353 : const uint32_t frameNumber );
354 :
355 : /**
356 : * Finish rendering a frame.
357 : *
358 : * Called once at the end of each frame, to do per-frame updates of
359 : * pipe-specific data, for example updating the rendering engine. Releases
360 : * the local synchronization if the thread model is local_sync. Always
361 : * releases the global synchronization for this pipe.
362 : *
363 : * This method has to call releaseFrame().
364 : *
365 : * @param frameID the per-frame identifier.
366 : * @param frameNumber the frame to finish.
367 : * @version 1.0
368 : */
369 : EQ_API virtual void frameFinish( const uint128_t& frameID,
370 : const uint32_t frameNumber );
371 :
372 : /**
373 : * Finish drawing.
374 : *
375 : * Called once per frame after the last draw operation. Releases the local
376 : * synchronization if the thread model is draw_sync (the default).
377 : *
378 : * @param frameID the per-frame identifier.
379 : * @param frameNumber the frame to finished with draw.
380 : * @version 1.0
381 : */
382 : EQ_API virtual void frameDrawFinish( const uint128_t& frameID,
383 : const uint32_t frameNumber );
384 :
385 : /** @internal */
386 : EQ_API virtual void attach( const uint128_t& id, const uint32_t instanceID );
387 :
388 : private:
389 : detail::Pipe* const _impl;
390 : friend class detail::RenderThread;
391 :
392 : //-------------------- Methods --------------------
393 : void _setupCommandQueue();
394 : void _setupAffinity();
395 : void _exitCommandQueue();
396 :
397 : /** @internal @return lunchbox::Thread::Affinity mask for this GPU. */
398 : EQ_API int32_t _getAutoAffinity() const;
399 : friend class detail::ThreadAffinityVisitor;
400 :
401 : //friend class Window;
402 :
403 : void _stopTransferThread();
404 :
405 : /** @internal Release the views not used for some revisions. */
406 : void _releaseViews();
407 :
408 : /** @internal Clear the view cache and release all views. */
409 : void _flushViews();
410 :
411 : /** @internal Clear the queue cache and release all queues. */
412 : void _flushQueues();
413 :
414 : /* The command functions. */
415 : bool _cmdCreateWindow( co::ICommand& command );
416 : bool _cmdDestroyWindow( co::ICommand& command );
417 : bool _cmdConfigInit( co::ICommand& command );
418 : bool _cmdConfigExit( co::ICommand& command );
419 : bool _cmdFrameStartClock( co::ICommand& command );
420 : bool _cmdFrameStart( co::ICommand& command );
421 : bool _cmdFrameFinish( co::ICommand& command );
422 : bool _cmdFrameDrawFinish( co::ICommand& command );
423 : bool _cmdExitThread( co::ICommand& command );
424 : bool _cmdDetachView( co::ICommand& command );
425 : bool _cmdExitTransferThread( co::ICommand& command );
426 :
427 92 : LB_TS_VAR( _pipeThread );
428 : };
429 : }
430 :
431 : #endif // EQ_PIPE_H
|