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_WINDOW_H
21 : #define EQ_WINDOW_H
22 :
23 : #include <eq/types.h>
24 : #include <eq/notifierInterface.h> // base class
25 : #include <eq/windowSettings.h> // template param
26 : #include <eq/visitorResult.h> // enum
27 :
28 : #include <eq/fabric/renderContext.h> // member
29 : #include <eq/fabric/window.h> // base class
30 : #include <eq/util/bitmapFont.h> // member
31 : #include <eq/util/objectManager.h> // member
32 :
33 :
34 : /** @file eq/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 explicit 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 3 : 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 1 : 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 0 : 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 @return shared context for used by the transfer thread. */
180 : EQ_API const GLEWContext* getTransferGlewContext() const;
181 :
182 : /**
183 : * @internal
184 : * @return the OpenGL texture format corresponding to the window's color
185 : * drawable configuration
186 : */
187 : EQ_API uint32_t getColorFormat() const;
188 : //@}
189 :
190 : /** @name Actions */
191 : //@{
192 : /**
193 : * Flush outstanding rendering requests.
194 : *
195 : * Called at the end of each frame from frameFinish() to ensure timely
196 : * execution of pending rendering requests.
197 : * @version 1.0
198 : */
199 : EQ_API virtual void flush() const;
200 :
201 : /**
202 : * Finish outstanding rendering requests.
203 : *
204 : * Called before a software swap barrier to ensure that the window will
205 : * swap directly after the barrier is left.
206 : * @version 1.0
207 : */
208 : EQ_API virtual void finish() const;
209 :
210 : /** Swap the front and back buffer of the window. @version 1.0 */
211 : EQ_API virtual void swapBuffers();
212 :
213 : /** Render the current framerate as on overlay. @version 1.0 */
214 : EQ_API virtual void drawFPS();
215 :
216 : /** @return the window's average framerate. @version 1.0 */
217 0 : float getFPS() const { return _avgFPS; }
218 :
219 : /**
220 : * Make the window's drawable and context current.
221 : *
222 : * GL drivers tend to behave sub-optimally if too many makeCurrent calls
223 : * happen in a multi-threaded program. When caching is enabled, this method
224 : * will only call SystemWindow::makeCurrent if it has not been done before
225 : * for this window on this thread.
226 : * @version 1.3.2
227 : */
228 : EQ_API virtual void makeCurrent( const bool cache = true ) const;
229 :
230 : /**
231 : * This results in no context being current in the current thread.
232 : * @version 1.10
233 : */
234 : EQ_API virtual void doneCurrent() const;
235 :
236 : /** @internal Bind the window's FBO, if it uses one. */
237 : EQ_API virtual void bindFrameBuffer() const;
238 :
239 : /** @internal Bind the window's draw (aka multisampled) FBO, if it uses one. */
240 : EQ_API virtual void bindDrawFrameBuffer() const;
241 :
242 : /** @internal Blit from multisampled FBO to window FBO */
243 : EQ_API virtual void updateFrameBuffer() const;
244 :
245 : /** @internal Notify this window that the viewport has changed. */
246 : EQ_API virtual void notifyViewportChanged();
247 : //@}
248 :
249 : /** @name SystemWindow interface */
250 : //@{
251 : /**
252 : * Set the OS-specific window.
253 : *
254 : * The SystemWindow implements the window-system-dependent part, e.g., the
255 : * drawable creation. This window forwards certain calls, e.g.,
256 : * swapBuffers(), to the SystemWindow. The system window has to be
257 : * initialized.
258 : * @version 1.0
259 : */
260 : EQ_API void setSystemWindow( SystemWindow* window );
261 :
262 : /** @return the OS-specific window implementation. @version 1.0 */
263 0 : const SystemWindow* getSystemWindow() const { return _systemWindow; }
264 :
265 : /** @return the OS-specific window implementation. @version 1.0 */
266 : SystemWindow* getSystemWindow() { return _systemWindow; }
267 :
268 : /** @return the OS-specific pipe implementation. @version 1.0 */
269 : const SystemPipe* getSystemPipe() const;
270 :
271 : /** @return the OS-specific pipe implementation. @version 1.0 */
272 : SystemPipe* getSystemPipe();
273 :
274 : /** @internal Create shared context window for asynchronuous usage. */
275 : bool createTransferWindow();
276 :
277 : /** @internal delete the shared context window. */
278 : void deleteTransferWindow();
279 :
280 : /** @internal @return the transfer window, or 0 if not created yet. */
281 : SystemWindow* getTransferWindow();
282 : const SystemWindow* getTransferWindow() const; //!< @internal
283 : //@}
284 :
285 : /** @name Events */
286 : //@{
287 : /**
288 : * Send a window error event to the application node.
289 : *
290 : * @param error the error code.
291 : * @version 1.7.1
292 : */
293 : EQ_API EventOCommand sendError( const uint32_t error ) final;
294 :
295 : /**
296 : * Process a received event.
297 : *
298 : * The task of this method is to update the window as necessary, and
299 : * transform the event into an config event to be send to the
300 : * application using Config::sendEvent(). Events which can be related to a
301 : * channel (eg pointer events) are transformed into their corresponding
302 : * channel event and forwarded to Channel::processEvent().
303 : *
304 : * @param event the received window system event.
305 : * @return true when the event was handled, false if not.
306 : * @version 1.0
307 : */
308 : EQ_API virtual bool processEvent( const Event& event );
309 : //@}
310 :
311 : protected:
312 : friend class Pipe;
313 :
314 : /** @internal */
315 : EQ_API virtual void attach( const uint128_t& id, const uint32_t instanceID );
316 :
317 : /** @name Actions */
318 : //@{
319 : /**
320 : * Start a frame by unlocking all child resources.
321 : *
322 : * @param frameNumber the frame to start.
323 : * @version 1.0
324 : */
325 : EQ_API void startFrame( const uint32_t frameNumber );
326 :
327 : /**
328 : * Signal the completion of a frame to the parent.
329 : *
330 : * @param frameNumber the frame to end.
331 : * @version 1.0
332 : */
333 : EQ_API void releaseFrame( const uint32_t frameNumber );
334 :
335 : /**
336 : * Signal the release of the local synchronization to the parent.
337 : *
338 : * @param frameNumber the frame to release.
339 : * @version 1.0
340 : */
341 : EQ_API void releaseFrameLocal( const uint32_t frameNumber );
342 : //@}
343 :
344 : /**
345 : * @name Callbacks
346 : *
347 : * The callbacks are called by Equalizer during rendering to execute
348 : * various actions.
349 : */
350 : //@{
351 : /**
352 : * Initialize this window.
353 : *
354 : * @param initID the init identifier.
355 : * @version 1.0
356 : */
357 : EQ_API virtual bool configInit( const uint128_t& initID );
358 :
359 : /**
360 : * Initialize the OS-specific window.
361 : *
362 : * @sa setSystemWindow()
363 : * @version 1.0
364 : */
365 : EQ_API virtual bool configInitSystemWindow( const uint128_t& initID );
366 :
367 : /**
368 : * Initialize the OpenGL state for this window.
369 : *
370 : * Called from configInit(), after the system window has been successfully
371 : * initialized.
372 : *
373 : * @param initID the init identifier.
374 : * @return true if the initialization was successful, false if not.
375 : * @version 1.0
376 : */
377 : EQ_API virtual bool configInitGL( const uint128_t& initID );
378 :
379 : /** Exit this window. @version 1.0 */
380 : EQ_API virtual bool configExit();
381 :
382 : /** De-initialize the OS-specific window. @version 1.0 */
383 : EQ_API virtual bool configExitSystemWindow();
384 :
385 : /** De-initialize the OpenGL state for this window. @version 1.0 */
386 0 : virtual bool configExitGL() { return true; }
387 :
388 : /**
389 : * Start rendering a frame.
390 : *
391 : * Called once at the beginning of each frame, to do per-frame updates
392 : * of window-specific data. This method has to call startFrame().
393 : *
394 : * @param frameID the per-frame identifier.
395 : * @param frameNumber the frame to start.
396 : * @version 1.0
397 : */
398 : EQ_API virtual void frameStart( const uint128_t& frameID,
399 : const uint32_t frameNumber );
400 :
401 : /**
402 : * Finish rendering a frame.
403 : *
404 : * Called once at the end of each frame, to do per-frame updates of
405 : * window-specific data. This method has to call releaseFrame(). The
406 : * default implementation also flushes all rendering commands. This
407 : * light-weight call ensures that all outstanding rendering commands for
408 : * the window's context are being executed in a timely fashion.
409 : *
410 : * @param frameID the per-frame identifier.
411 : * @param frameNumber the frame to finish.
412 : * @version 1.0
413 : */
414 : EQ_API virtual void frameFinish( const uint128_t& frameID,
415 : const uint32_t frameNumber );
416 :
417 : /**
418 : * Finish drawing.
419 : *
420 : * Called once per frame after the last draw operation. Typically
421 : * releases the local node thread synchronization for this frame.
422 : *
423 : * @param frameID the per-frame identifier.
424 : * @param frameNumber the frame to finished with draw.
425 : * @version 1.0
426 : */
427 : EQ_API virtual void frameDrawFinish( const uint128_t& frameID,
428 : const uint32_t frameNumber );
429 : //@}
430 :
431 : private:
432 : enum State
433 : {
434 : STATE_STOPPED,
435 : STATE_INITIALIZING,
436 : STATE_RUNNING,
437 : STATE_FAILED
438 : };
439 :
440 : /** The window sharing the OpenGL context. */
441 : const Window* _sharedContextWindow;
442 :
443 : /** Transfer window */
444 : SystemWindow* _transferWindow;
445 :
446 : /** Window-system specific functions class */
447 : SystemWindow* _systemWindow;
448 :
449 : /** The configInit/configExit state. */
450 : State _state;
451 :
452 : /** OpenGL object management. */
453 : util::ObjectManager _objectManager;
454 :
455 : /** Used to calculate time of last frame rendering */
456 : float _lastTime;
457 :
458 : /** averaged FPS value, to prevent FPS counter flickering */
459 : float _avgFPS;
460 :
461 : /** The list of render context used since the last frame start. */
462 : std::vector< RenderContext > _renderContexts[2];
463 : enum
464 : {
465 : FRONT = 0,
466 : BACK = 1
467 : };
468 :
469 : /** The time of the last swap command. */
470 : int64_t _lastSwapTime;
471 :
472 : /** List of channels that have grabbed the mouse. */
473 : Channels _grabbedChannels;
474 :
475 : struct Private;
476 : Private* _private; // placeholder for binary-compatible changes
477 :
478 : /** Add a channel's rendering context to the current frame's list */
479 : void _addRenderContext( const RenderContext& context );
480 : friend class Channel;
481 :
482 : /** @return the channels concerned by the given mouse event. */
483 : Channels _getEventChannels( const PointerEvent& event );
484 :
485 : /** Set up object manager during initialization. */
486 : void _setupObjectManager();
487 : /** Release object manager. */
488 : void _releaseObjectManager();
489 :
490 : /** Calculates per-window frame rate */
491 : void _updateFPS();
492 :
493 : /** Enter the given barrier. */
494 : void _enterBarrier( co::ObjectVersion barrier );
495 :
496 : void _updateEvent( Event& event );
497 :
498 : /* The command functions. */
499 : bool _cmdCreateChannel( co::ICommand& command );
500 : bool _cmdDestroyChannel(co::ICommand& command );
501 : bool _cmdConfigInit( co::ICommand& command );
502 : bool _cmdConfigExit( co::ICommand& command );
503 : bool _cmdFrameStart( co::ICommand& command );
504 : bool _cmdFrameFinish( co::ICommand& command );
505 : bool _cmdThrottleFramerate( co::ICommand& command );
506 : bool _cmdFlush( co::ICommand& command );
507 : bool _cmdFinish( co::ICommand& command );
508 : bool _cmdBarrier( co::ICommand& command );
509 : bool _cmdNVBarrier( co::ICommand& command );
510 : bool _cmdSwap( co::ICommand& command );
511 : bool _cmdFrameDrawFinish( co::ICommand& command );
512 :
513 272 : LB_TS_VAR( _pipeThread )
514 : };
515 : }
516 :
517 : #endif // EQ_WINDOW_H
|