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-2014, 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_WINDOW_H
21 : #define EQ_WINDOW_H
22 :
23 : #include <eq/client/types.h>
24 : #include <eq/client/windowSettings.h> // template param
25 : #include <eq/client/visitorResult.h> // enum
26 :
27 : #include <eq/util/bitmapFont.h> // member
28 : #include <eq/fabric/renderContext.h> // member
29 : #include <eq/fabric/window.h> // base class
30 : #include <eq/client/notifierInterface.h> // base class
31 :
32 :
33 :
34 : /** @file eq/client/window.h */
35 :
36 : namespace eq
37 : {
38 : /**
39 : * A Window represents an on-screen or off-screen drawable.
40 : *
41 : * A drawable is a 2D rendering surface, typically attached to an OpenGL
42 : * context. A window uses an SystemWindow implementation to manage the operating
43 : * system specific handling of window and context creation.
44 : *
45 : * A Window is a child of a Pipe. The task methods for all windows of a pipe are
46 : * executed in the same pipe thread. All window and subsequent channel task
47 : * methods are executed in the order the windows are defined on the pipe, with
48 : * the exception of the swap and finish tasks, which are executed after all
49 : * windows have been updated. This ensures that all windows of a given pipe swap
50 : * at the same time.
51 : *
52 : * The default window initialization methods initialize all windows of the same
53 : * pipe with a shared context, so that OpenGL objects can be reused between them
54 : * for optimal GPU memory usage. The window facilitates OpenGL object management
55 : * by providing an ObjectManager for allocating and sharing OpenGL objects.
56 : *
57 : * Please note that each window potentially has its own OpenGL command buffer,
58 : * thus glFlush is needed to synchronize the state of OpenGL objects between
59 : * windows. Therefore, Equalizer calls flush() at the end of each frame for each
60 : * window.
61 : *
62 : * @sa fabric::Window
63 : */
64 : class Window : public fabric::Window< Pipe, Window, Channel, WindowSettings >,
65 : public NotifierInterface
66 : {
67 : public:
68 : /** Construct a new window. @version 1.0 */
69 : EQ_API Window( Pipe* parent );
70 :
71 : /** Destruct the window. @version 1.0 */
72 : EQ_API virtual ~Window();
73 :
74 : /** @name Data Access */
75 : //@{
76 : EQ_API co::CommandQueue* getPipeThreadQueue(); //!< @internal
77 : EQ_API co::CommandQueue* getCommandThreadQueue(); //!< @internal
78 : EQ_API uint32_t getCurrentFrame() const; //!< @internal render thr only
79 :
80 : /** @return the Node of this window. @version 1.0 */
81 : EQ_API const Node* getNode() const;
82 :
83 : /** @return the Node of this window. @version 1.0 */
84 : EQ_API Node* getNode();
85 :
86 : /** @return the Config of this window. @version 1.0 */
87 : EQ_API const Config* getConfig() const;
88 :
89 : /** @return the Config of this window. @version 1.0 */
90 : EQ_API Config* getConfig();
91 :
92 : /** @return the Client of this window. @version 1.0 */
93 : EQ_API ClientPtr getClient();
94 :
95 : /** @return the Server of this window. @version 1.0 */
96 : EQ_API ServerPtr getServer();
97 :
98 : /**
99 : * @return true if this window is running, false otherwise.
100 : * @version 1.0
101 : */
102 53 : bool isRunning() const { return (_state == STATE_RUNNING); }
103 :
104 : /**
105 : * @return true if this window is stopped, false otherwise.
106 : * @version 1.0
107 : */
108 15 : bool isStopped() const { return (_state == STATE_STOPPED); }
109 :
110 : /**
111 : * Get the last rendering context at the x, y position.
112 : *
113 : * If no render context is found on the given position, false is returned
114 : * and context is not modified.
115 : *
116 : * @return true if a render context was found, false otherwise.
117 : * @warning experimental - may not be supported in the future.
118 : */
119 : EQ_API bool getRenderContext( const int32_t x, const int32_t y,
120 : RenderContext& context ) const;
121 : //@}
122 :
123 : /** @name OpenGL context handling and sharing */
124 : //@{
125 : /**
126 : * Set the window with which this window shares the OpenGL context.
127 : *
128 : * By default it is set to the first window of the pipe in the window's
129 : * constructor. The shared context window is used during initialization to
130 : * setup the OpenGL context and util::ObjectManager. The default
131 : * implementation of configInitSystemWindow() will use this to call
132 : * WindowSettings::setSharedContextWindow() using the corresponding
133 : * SystemWindow.
134 : * @version 1.0
135 : */
136 : EQ_API void setSharedContextWindow( const Window* sharedContextWindow );
137 :
138 : /**
139 : * @return the window with which this window shares the GL context.
140 : * @version 1.0
141 : */
142 : EQ_API const Window* getSharedContextWindow() const;
143 :
144 : /** @return the window's object manager instance. @version 1.0 */
145 9 : util::ObjectManager& getObjectManager() { return _objectManager; }
146 :
147 : /** @return the window's object manager instance. @version 1.0 */
148 : const util::ObjectManager& getObjectManager() const
149 : { return _objectManager; }
150 :
151 : /**
152 : * @return a small bitmap font used for overlays.
153 : * @warning experimental - may not be supported in the future.
154 : */
155 : EQ_API const util::BitmapFont* getSmallFont();
156 :
157 : /**
158 : * @return a medium bitmap font used for overlays.
159 : * @warning experimental - may not be supported in the future.
160 : */
161 : EQ_API const util::BitmapFont* getMediumFont();
162 :
163 : /**
164 : * Get the GLEW context for this window.
165 : *
166 : * The glew context is provided and initialized by the SystemWindow, and
167 : * provides access to OpenGL extensions. This function does not follow the
168 : * Equalizer naming conventions, since GLEW uses a function of this name to
169 : * automatically resolve OpenGL function entry points. Therefore, any OpenGL
170 : * function support by the driver can be directly called from any method of
171 : * an initialized window.
172 : *
173 : * @return the extended OpenGL function table for the window's OpenGL
174 : * context.
175 : * @version 1.0
176 : */
177 : EQ_API const GLEWContext* glewGetContext() const;
178 :
179 : /** @internal
180 : * Creates second system window if necessary and returns its context.
181 : *
182 : * Should be called from the pipe transfer thread.
183 : *
184 : * @return shared context for use in the transfer thread.
185 : */
186 : EQ_API const GLEWContext* getTransferGlewContext();
187 :
188 : /**
189 : * @internal
190 : * @return the OpenGL texture format corresponding to the window's color
191 : * drawable configuration
192 : */
193 : EQ_API uint32_t getColorFormat() const;
194 : //@}
195 :
196 : /** @name Actions */
197 : //@{
198 : /**
199 : * Flush outstanding rendering requests.
200 : *
201 : * Called at the end of each frame from frameFinish() to ensure timely
202 : * execution of pending rendering requests.
203 : * @version 1.0
204 : */
205 : EQ_API virtual void flush() const;
206 :
207 : /**
208 : * Finish outstanding rendering requests.
209 : *
210 : * Called before a software swap barrier to ensure that the window will
211 : * swap directly after the barrier is left.
212 : * @version 1.0
213 : */
214 : EQ_API virtual void finish() const;
215 :
216 : /** Swap the front and back buffer of the window. @version 1.0 */
217 : EQ_API virtual void swapBuffers();
218 :
219 : /** Render the current framerate as on overlay. @version 1.0 */
220 : EQ_API virtual void drawFPS();
221 :
222 : /** @return the window's average framerate. @version 1.0 */
223 0 : float getFPS() const { return _avgFPS; }
224 :
225 : /**
226 : * Make the window's drawable and context current.
227 : *
228 : * GL drivers tend to behave sub-optimally if too many makeCurrent calls
229 : * happen in a multi-threaded program. When caching is enabled, this method
230 : * will only call SystemWindow::makeCurrent if it has not been done before
231 : * for this window on this thread.
232 : * @version 1.3.2
233 : */
234 : EQ_API virtual void makeCurrent( const bool cache = true ) const;
235 :
236 : /** @internal
237 : * Make the shared transfer window's drawable and context current.
238 : */
239 : void makeCurrentTransfer( const bool cache = true ) const;
240 :
241 : /** @internal Bind the window's FBO, if it uses one. */
242 : EQ_API virtual void bindFrameBuffer() const;
243 :
244 : /** @internal Notify this window that the viewport has changed. */
245 : EQ_API virtual void notifyViewportChanged();
246 : //@}
247 :
248 : /** @name SystemWindow interface */
249 : //@{
250 : /**
251 : * Set the OS-specific window.
252 : *
253 : * The SystemWindow implements the window-system-dependent part, e.g., the
254 : * drawable creation. This window forwards certain calls, e.g.,
255 : * swapBuffers(), to the SystemWindow. The system window has to be
256 : * initialized.
257 : * @version 1.0
258 : */
259 : EQ_API void setSystemWindow( SystemWindow* window );
260 :
261 : /** @return the OS-specific window implementation. @version 1.0 */
262 49 : const SystemWindow* getSystemWindow() const { return _systemWindow; }
263 :
264 : /** @return the OS-specific window implementation. @version 1.0 */
265 : SystemWindow* getSystemWindow() { return _systemWindow; }
266 :
267 : /** @return the OS-specific pipe implementation. @version 1.0 */
268 : const SystemPipe* getSystemPipe() const;
269 :
270 : /** @return the OS-specific pipe implementation. @version 1.0 */
271 : SystemPipe* getSystemPipe();
272 :
273 : /** @internal Create shared context window for asynchronuous usage. */
274 : bool createTransferWindow();
275 :
276 : /** @internal delete the shared context window. */
277 : void deleteTransferSystemWindow();
278 : //@}
279 :
280 : /** @name Events */
281 : //@{
282 : /**
283 : * Send a window error event to the application node.
284 : *
285 : * @param error the error code.
286 : * @version 1.7.1
287 : */
288 : EQ_API EventOCommand sendError( const uint32_t error ) final;
289 :
290 : /**
291 : * Process a received event.
292 : *
293 : * The task of this method is to update the window as necessary, and
294 : * transform the event into an config event to be send to the
295 : * application using Config::sendEvent().
296 : *
297 : * @param event the received window system event.
298 : * @return true when the event was handled, false if not.
299 : * @version 1.0
300 : */
301 : EQ_API virtual bool processEvent( const Event& event );
302 : //@}
303 :
304 : protected:
305 : friend class Pipe;
306 :
307 : /** @internal */
308 : EQ_API virtual void attach( const uint128_t& id, const uint32_t instanceID );
309 :
310 : /** @name Actions */
311 : //@{
312 : /**
313 : * Start a frame by unlocking all child resources.
314 : *
315 : * @param frameNumber the frame to start.
316 : * @version 1.0
317 : */
318 : EQ_API void startFrame( const uint32_t frameNumber );
319 :
320 : /**
321 : * Signal the completion of a frame to the parent.
322 : *
323 : * @param frameNumber the frame to end.
324 : * @version 1.0
325 : */
326 : EQ_API void releaseFrame( const uint32_t frameNumber );
327 :
328 : /**
329 : * Signal the release of the local synchronization to the parent.
330 : *
331 : * @param frameNumber the frame to release.
332 : * @version 1.0
333 : */
334 : EQ_API void releaseFrameLocal( const uint32_t frameNumber );
335 : //@}
336 :
337 : /**
338 : * @name Callbacks
339 : *
340 : * The callbacks are called by Equalizer during rendering to execute
341 : * various actions.
342 : */
343 : //@{
344 : /**
345 : * Initialize this window.
346 : *
347 : * @param initID the init identifier.
348 : * @version 1.0
349 : */
350 : EQ_API virtual bool configInit( const uint128_t& initID );
351 :
352 : /**
353 : * Initialize the OS-specific window.
354 : *
355 : * @sa setSystemWindow()
356 : * @version 1.0
357 : */
358 : EQ_API virtual bool configInitSystemWindow( const uint128_t& initID );
359 :
360 : /**
361 : * Initialize the OpenGL state for this window.
362 : *
363 : * @param initID the init identifier.
364 : * @return <code>true</code> if the initialization was successful,
365 : * <code>false</code> if not.
366 : * @version 1.0
367 : */
368 : EQ_API virtual bool configInitGL( const uint128_t& initID );
369 :
370 : /** Exit this window. @version 1.0 */
371 : EQ_API virtual bool configExit();
372 :
373 : /** De-initialize the OS-specific window. @version 1.0 */
374 : EQ_API virtual bool configExitSystemWindow();
375 :
376 : /** De-initialize the OpenGL state for this window. @version 1.0 */
377 15 : virtual bool configExitGL() { return true; }
378 :
379 : /**
380 : * Start rendering a frame.
381 : *
382 : * Called once at the beginning of each frame, to do per-frame updates
383 : * of window-specific data. This method has to call startFrame().
384 : *
385 : * @param frameID the per-frame identifier.
386 : * @param frameNumber the frame to start.
387 : * @version 1.0
388 : */
389 : EQ_API virtual void frameStart( const uint128_t& frameID,
390 : const uint32_t frameNumber );
391 :
392 : /**
393 : * Finish rendering a frame.
394 : *
395 : * Called once at the end of each frame, to do per-frame updates of
396 : * window-specific data. This method has to call releaseFrame(). The
397 : * default implementation also flushes all rendering commands. This
398 : * light-weight call ensures that all outstanding rendering commands for
399 : * the window's context are being executed in a timely fashion.
400 : *
401 : * @param frameID the per-frame identifier.
402 : * @param frameNumber the frame to finish.
403 : * @version 1.0
404 : */
405 : EQ_API virtual void frameFinish( const uint128_t& frameID,
406 : const uint32_t frameNumber );
407 :
408 : /**
409 : * Finish drawing.
410 : *
411 : * Called once per frame after the last draw operation. Typically
412 : * releases the local node thread synchronization for this frame.
413 : *
414 : * @param frameID the per-frame identifier.
415 : * @param frameNumber the frame to finished with draw.
416 : * @version 1.0
417 : */
418 : EQ_API virtual void frameDrawFinish( const uint128_t& frameID,
419 : const uint32_t frameNumber );
420 : //@}
421 :
422 : private:
423 : enum State
424 : {
425 : STATE_STOPPED,
426 : STATE_INITIALIZING,
427 : STATE_RUNNING,
428 : STATE_FAILED
429 : };
430 :
431 : /** The window sharing the OpenGL context. */
432 : const Window* _sharedContextWindow;
433 :
434 : /** Transfer window */
435 : SystemWindow* _transferWindow;
436 :
437 : /** Window-system specific functions class */
438 : SystemWindow* _systemWindow;
439 :
440 : /** The configInit/configExit state. */
441 : State _state;
442 :
443 : /** OpenGL object management. */
444 : util::ObjectManager _objectManager;
445 :
446 : /** Used to calculate time of last frame rendering */
447 : float _lastTime;
448 :
449 : /** averaged FPS value, to prevent FPS counter flickering */
450 : float _avgFPS;
451 :
452 : /** The list of render context used since the last frame start. */
453 : std::vector< RenderContext > _renderContexts[2];
454 : enum
455 : {
456 : FRONT = 0,
457 : BACK = 1
458 : };
459 :
460 : /** The time of the last swap command. */
461 : int64_t _lastSwapTime;
462 :
463 : /** List of channels that have grabbed the mouse. */
464 : Channels _grabbedChannels;
465 :
466 : struct Private;
467 : Private* _private; // placeholder for binary-compatible changes
468 :
469 : /** Add a channel's rendering context to the current frame's list */
470 : void _addRenderContext( const RenderContext& context );
471 : friend class Channel;
472 :
473 : /** @return the channels concerned by the given mouse event. */
474 : Channels _getEventChannels( const PointerEvent& event );
475 :
476 : /** Set up object manager during initialization. */
477 : void _setupObjectManager();
478 : /** Release object manager. */
479 : void _releaseObjectManager();
480 :
481 : /** Calculates per-window frame rate */
482 : void _updateFPS();
483 :
484 : /** Enter the given barrier. */
485 : void _enterBarrier( co::ObjectVersion barrier );
486 :
487 : void _updateEvent( Event& event );
488 :
489 : /* The command functions. */
490 : bool _cmdCreateChannel( co::ICommand& command );
491 : bool _cmdDestroyChannel(co::ICommand& command );
492 : bool _cmdConfigInit( co::ICommand& command );
493 : bool _cmdConfigExit( co::ICommand& command );
494 : bool _cmdFrameStart( co::ICommand& command );
495 : bool _cmdFrameFinish( co::ICommand& command );
496 : bool _cmdThrottleFramerate( co::ICommand& command );
497 : bool _cmdFlush( co::ICommand& command );
498 : bool _cmdFinish( co::ICommand& command );
499 : bool _cmdBarrier( co::ICommand& command );
500 : bool _cmdNVBarrier( co::ICommand& command );
501 : bool _cmdSwap( co::ICommand& command );
502 : bool _cmdFrameDrawFinish( co::ICommand& command );
503 :
504 300 : LB_TS_VAR( _pipeThread );
505 : };
506 : }
507 :
508 : #endif // EQ_WINDOW_H
|