Line data Source code
1 : /* Copyright (c) 2005-2017, Stefan Eilemann <eile@equalizergraphics.com>
2 : * Cedric Stalder <cedric.stalder@gmail.com>
3 : * Daniel Nachbaur <danielnachbaur@gmail.com>
4 : *
5 : * This library is free software; you can redistribute it and/or modify it under
6 : * the terms of the GNU Lesser General Public License version 2.1 as published
7 : * by the Free Software Foundation.
8 : *
9 : * This library is distributed in the hope that it will be useful, but WITHOUT
10 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12 : * details.
13 : *
14 : * You should have received a copy of the GNU Lesser General Public License
15 : * along with this library; if not, write to the Free Software Foundation, Inc.,
16 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 : */
18 :
19 : #ifndef EQ_WINDOW_H
20 : #define EQ_WINDOW_H
21 :
22 : #include <eq/notifierInterface.h> // base class
23 : #include <eq/types.h>
24 : #include <eq/visitorResult.h> // enum
25 : #include <eq/windowSettings.h> // template param
26 :
27 : #include <eq/fabric/renderContext.h> // member
28 : #include <eq/fabric/window.h> // base class
29 : #include <eq/util/bitmapFont.h> // member
30 : #include <eq/util/objectManager.h> // member
31 :
32 : /** @file eq/window.h */
33 :
34 : namespace eq
35 : {
36 : /**
37 : * A Window represents an on-screen or off-screen drawable.
38 : *
39 : * A drawable is a 2D rendering surface, typically attached to an OpenGL
40 : * context. A window uses an SystemWindow implementation to manage the operating
41 : * system specific handling of window and context creation.
42 : *
43 : * A Window is a child of a Pipe. The task methods for all windows of a pipe are
44 : * executed in the same pipe thread. All window and subsequent channel task
45 : * methods are executed in the order the windows are defined on the pipe, with
46 : * the exception of the swap and finish tasks, which are executed after all
47 : * windows have been updated. This ensures that all windows of a given pipe swap
48 : * at the same time.
49 : *
50 : * The default window initialization methods initialize all windows of the same
51 : * pipe with a shared context, so that OpenGL objects can be reused between them
52 : * for optimal GPU memory usage. The window facilitates OpenGL object management
53 : * by providing an ObjectManager for allocating and sharing OpenGL objects.
54 : *
55 : * Please note that each window potentially has its own OpenGL command buffer,
56 : * thus glFlush is needed to synchronize the state of OpenGL objects between
57 : * windows. Therefore, Equalizer calls flush() at the end of each frame for each
58 : * window.
59 : *
60 : * @sa fabric::Window
61 : */
62 : class Window : public fabric::Window<Pipe, Window, Channel, WindowSettings>,
63 : public NotifierInterface
64 : {
65 : public:
66 : /** Construct a new window. @version 1.0 */
67 : EQ_API explicit Window(Pipe* parent);
68 :
69 : /** Destruct the window. @version 1.0 */
70 : EQ_API virtual ~Window();
71 :
72 : /** @name Data Access */
73 : //@{
74 : EQ_API co::CommandQueue* getPipeThreadQueue(); //!< @internal
75 : EQ_API co::CommandQueue* getCommandThreadQueue(); //!< @internal
76 : EQ_API uint32_t getCurrentFrame() const; //!< @internal render thr only
77 :
78 : /** @return the Node of this window. @version 1.0 */
79 : EQ_API const Node* getNode() const;
80 :
81 : /** @return the Node of this window. @version 1.0 */
82 : EQ_API Node* getNode();
83 :
84 : /** @return the Config of this window. @version 1.0 */
85 : EQ_API const Config* getConfig() const;
86 :
87 : /** @return the Config of this window. @version 1.0 */
88 : EQ_API Config* getConfig();
89 :
90 : /** @return the Client of this window. @version 1.0 */
91 : EQ_API ClientPtr getClient();
92 :
93 : /** @return the Server of this window. @version 1.0 */
94 : EQ_API ServerPtr getServer();
95 :
96 : /**
97 : * @return true if this window is running, false otherwise.
98 : * @version 1.0
99 : */
100 7 : bool isRunning() const { return (_state == STATE_RUNNING); }
101 : /**
102 : * @return true if this window is stopped, false otherwise.
103 : * @version 1.0
104 : */
105 2 : bool isStopped() const { return (_state == STATE_STOPPED); }
106 : /**
107 : * Get the last rendering context at the x, y position.
108 : *
109 : * If no render context is found on the given position, false is returned
110 : * and context is not modified.
111 : *
112 : * @return true if a render context was found, false otherwise.
113 : * @warning experimental - may not be supported in the future.
114 : */
115 : EQ_API bool getRenderContext(const int32_t x, const int32_t y,
116 : RenderContext& context) const;
117 : //@}
118 :
119 : /** @name OpenGL context handling and sharing */
120 : //@{
121 : /**
122 : * Set the window with which this window shares the OpenGL context.
123 : *
124 : * By default it is set to the first window of the pipe in the window's
125 : * constructor. The shared context window is used during initialization to
126 : * setup the OpenGL context and util::ObjectManager. The default
127 : * implementation of configInitSystemWindow() will use this to call
128 : * WindowSettings::setSharedContextWindow() using the corresponding
129 : * SystemWindow.
130 : * @version 1.0
131 : */
132 : EQ_API void setSharedContextWindow(const Window* sharedContextWindow);
133 :
134 : /**
135 : * @return the window with which this window shares the GL context.
136 : * @version 1.0
137 : */
138 : EQ_API const Window* getSharedContextWindow() const;
139 :
140 : /** @return the window's object manager instance. @version 1.0 */
141 6 : util::ObjectManager& getObjectManager() { return _objectManager; }
142 : /** @return the window's object manager instance. @version 1.0 */
143 : const util::ObjectManager& getObjectManager() const
144 : {
145 : return _objectManager;
146 : }
147 :
148 : /**
149 : * @return a small bitmap font used for overlays.
150 : * @warning experimental - may not be supported in the future.
151 : */
152 : EQ_API const util::BitmapFont* getSmallFont();
153 :
154 : /**
155 : * @return a medium bitmap font used for overlays.
156 : * @warning experimental - may not be supported in the future.
157 : */
158 : EQ_API const util::BitmapFont* getMediumFont();
159 :
160 : /**
161 : * Get the GLEW context for this window.
162 : *
163 : * The glew context is provided and initialized by the SystemWindow, and
164 : * provides access to OpenGL extensions. This function does not follow the
165 : * Equalizer naming conventions, since GLEW uses a function of this name to
166 : * automatically resolve OpenGL function entry points. Therefore, any OpenGL
167 : * function support by the driver can be directly called from any method of
168 : * an initialized window.
169 : *
170 : * @return the extended OpenGL function table for the window's OpenGL
171 : * context.
172 : * @version 1.0
173 : */
174 : EQ_API const GLEWContext* glewGetContext() const;
175 :
176 : /** @internal @return shared context for used by the transfer thread. */
177 : EQ_API const GLEWContext* getTransferGlewContext() const;
178 :
179 : /**
180 : * @internal
181 : * @return the OpenGL texture format corresponding to the window's color
182 : * drawable configuration
183 : */
184 : EQ_API uint32_t getColorFormat() const;
185 : //@}
186 :
187 : /** @name Actions */
188 : //@{
189 : /**
190 : * Flush outstanding rendering requests.
191 : *
192 : * Called at the end of each frame from frameFinish() to ensure timely
193 : * execution of pending rendering requests.
194 : * @version 1.0
195 : */
196 : EQ_API virtual void flush() const;
197 :
198 : /**
199 : * Finish outstanding rendering requests.
200 : *
201 : * Called before a software swap barrier to ensure that the window will
202 : * swap directly after the barrier is left.
203 : * @version 1.0
204 : */
205 : EQ_API virtual void finish() const;
206 :
207 : /** Swap the front and back buffer of the window. @version 1.0 */
208 : EQ_API virtual void swapBuffers();
209 :
210 : /** Render the current framerate as on overlay. @version 1.0 */
211 : EQ_API virtual void drawFPS();
212 :
213 : /** @return the window's average framerate. @version 1.0 */
214 0 : float getFPS() const { return _avgFPS; }
215 : /**
216 : * Make the window's drawable and context current.
217 : *
218 : * GL drivers tend to behave sub-optimally if too many makeCurrent calls
219 : * happen in a multi-threaded program. When caching is enabled, this method
220 : * will only call SystemWindow::makeCurrent if it has not been done before
221 : * for this window on this thread.
222 : * @version 1.3.2
223 : */
224 : EQ_API virtual void makeCurrent(const bool cache = true) const;
225 :
226 : /**
227 : * This results in no context being current in the current thread.
228 : * @version 1.10
229 : */
230 : EQ_API virtual void doneCurrent() const;
231 :
232 : /** @internal Bind the window's FBO, if it uses one. */
233 : EQ_API virtual void bindFrameBuffer() const;
234 :
235 : /** @internal Bind the window's draw (aka multisampled) FBO, if it uses one.
236 : */
237 : EQ_API virtual void bindDrawFrameBuffer() const;
238 :
239 : /** @internal Blit from multisampled FBO to window FBO */
240 : EQ_API virtual void updateFrameBuffer() const;
241 :
242 : /** @internal Notify this window that the viewport has changed. */
243 : EQ_API void notifyViewportChanged() override;
244 : //@}
245 :
246 : /** @name SystemWindow interface */
247 : //@{
248 : /**
249 : * Set the OS-specific window.
250 : *
251 : * The SystemWindow implements the window-system-dependent part, e.g., the
252 : * drawable creation. This window forwards certain calls, e.g.,
253 : * swapBuffers(), to the SystemWindow. The system window has to be
254 : * initialized.
255 : * @version 1.0
256 : */
257 : EQ_API void setSystemWindow(SystemWindow* window);
258 :
259 : /** @return the OS-specific window implementation. @version 1.0 */
260 24 : const SystemWindow* getSystemWindow() const { return _systemWindow; }
261 : /** @return the OS-specific window implementation. @version 1.0 */
262 0 : SystemWindow* getSystemWindow() { return _systemWindow; }
263 : /** @return the OS-specific pipe implementation. @version 1.0 */
264 : const SystemPipe* getSystemPipe() const;
265 :
266 : /** @return the OS-specific pipe implementation. @version 1.0 */
267 : SystemPipe* getSystemPipe();
268 :
269 : /** @internal Create shared context window for asynchronuous usage. */
270 : bool createTransferWindow();
271 :
272 : /** @internal delete the shared context window. */
273 : void deleteTransferWindow();
274 :
275 : /** @internal @return the transfer window, or 0 if not created yet. */
276 : SystemWindow* getTransferWindow();
277 : const SystemWindow* getTransferWindow() const; //!< @internal
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 : /** @sa NotifierInterface::processEvent(). */
291 : EQ_API bool processEvent(EventType type) override;
292 :
293 : /** @sa NotifierInterface::processEvent(). */
294 : EQ_API bool processEvent(EventType type, SizeEvent& event) override;
295 :
296 : /** @sa NotifierInterface::processEvent(). */
297 : EQ_API bool processEvent(EventType type, PointerEvent& event) override;
298 :
299 : /** @sa NotifierInterface::processEvent(). */
300 : EQ_API bool processEvent(EventType type, KeyEvent& event) override;
301 :
302 : /** @sa NotifierInterface::processEvent(). */
303 : EQ_API bool processEvent(AxisEvent& event) override;
304 :
305 : /** @sa NotifierInterface::processEvent(). */
306 : EQ_API bool processEvent(ButtonEvent& event) override;
307 :
308 : EQ_API bool processEvent(Statistic& event);
309 : //@}
310 :
311 : protected:
312 : friend class Pipe;
313 :
314 : /** @internal */
315 : EQ_API
316 : void attach(const uint128_t& id, const uint32_t instanceID) override;
317 :
318 : /** @name Actions */
319 : //@{
320 : /**
321 : * Start a frame by unlocking all child resources.
322 : *
323 : * @param frameNumber the frame to start.
324 : * @version 1.0
325 : */
326 : EQ_API void startFrame(const uint32_t frameNumber);
327 :
328 : /**
329 : * Signal the completion of a frame to the parent.
330 : *
331 : * @param frameNumber the frame to end.
332 : * @version 1.0
333 : */
334 : EQ_API void releaseFrame(const uint32_t frameNumber);
335 :
336 : /**
337 : * Signal the release of the local synchronization to the parent.
338 : *
339 : * @param frameNumber the frame to release.
340 : * @version 1.0
341 : */
342 : EQ_API void releaseFrameLocal(const uint32_t frameNumber);
343 : //@}
344 :
345 : /**
346 : * @name Callbacks
347 : *
348 : * The callbacks are called by Equalizer during rendering to execute
349 : * various actions.
350 : */
351 : //@{
352 : /**
353 : * Initialize this window.
354 : *
355 : * @param initID the init identifier.
356 : * @version 1.0
357 : */
358 : EQ_API virtual bool configInit(const uint128_t& initID);
359 :
360 : /**
361 : * Initialize the OS-specific window.
362 : *
363 : * @sa setSystemWindow()
364 : * @version 1.0
365 : */
366 : EQ_API virtual bool configInitSystemWindow(const uint128_t& initID);
367 :
368 : /**
369 : * Initialize the OpenGL state for this window.
370 : *
371 : * Called from configInit(), after the system window has been successfully
372 : * initialized.
373 : *
374 : * @param initID the init identifier.
375 : * @return true if the initialization was successful, false if not.
376 : * @version 1.0
377 : */
378 : EQ_API virtual bool configInitGL(const uint128_t& initID);
379 :
380 : /** Exit this window. @version 1.0 */
381 : EQ_API virtual bool configExit();
382 :
383 : /** De-initialize the OS-specific window. @version 1.0 */
384 : EQ_API virtual bool configExitSystemWindow();
385 :
386 : /** De-initialize the OpenGL state for this window. @version 1.0 */
387 2 : virtual bool configExitGL() { return true; }
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 : /* The command functions. */
497 : bool _cmdCreateChannel(co::ICommand& command);
498 : bool _cmdDestroyChannel(co::ICommand& command);
499 : bool _cmdConfigInit(co::ICommand& command);
500 : bool _cmdConfigExit(co::ICommand& command);
501 : bool _cmdFrameStart(co::ICommand& command);
502 : bool _cmdFrameFinish(co::ICommand& command);
503 : bool _cmdThrottleFramerate(co::ICommand& command);
504 : bool _cmdFlush(co::ICommand& command);
505 : bool _cmdFinish(co::ICommand& command);
506 : bool _cmdBarrier(co::ICommand& command);
507 : bool _cmdNVBarrier(co::ICommand& command);
508 : bool _cmdSwap(co::ICommand& command);
509 : bool _cmdFrameDrawFinish(co::ICommand& command);
510 : bool _cmdResize(co::ICommand& command);
511 :
512 4 : LB_TS_VAR(_pipeThread)
513 : };
514 : }
515 :
516 : #endif // EQ_WINDOW_H
|