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