2 ******************************************************************************
4 * @file qtwindowingsystem.cpp
5 * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
11 *****************************************************************************/
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "qtwindowingsystem.h"
32 #include <osg/DeleteHandler>
33 #include <osg/Version>
34 #include <osgViewer/GraphicsWindow>
36 #include <QOpenGLContext>
37 #include <QOffscreenSurface>
42 // TODO no need to derive from GraphicsWindow (derive directly from GraphicsContext instead)
43 class GraphicsWindowQt
: public osgViewer::GraphicsWindow
{
45 GraphicsWindowQt(osg::GraphicsContext::Traits
*traits
);
48 bool isSameKindAs(const Object
*object
) const
50 return dynamic_cast<const GraphicsWindowQt
*>(object
) != 0;
52 const char *libraryName() const
54 return "osgViewerXYZ";
56 const char *className() const
58 return "GraphicsWindowQt";
61 bool setWindowRectangleImplementation(int x
, int y
, int width
, int height
);
62 void getWindowRectangle(int & x
, int & y
, int & width
, int & height
);
63 bool setWindowDecorationImplementation(bool windowDecoration
);
64 bool getWindowDecoration() const;
66 void grabFocusIfPointerInWindow();
68 void setWindowName(const std::string
& name
);
69 std::string
getWindowName();
70 void useCursor(bool cursorOn
);
71 void setCursor(MouseCursor cursor
);
73 bool realizeImplementation();
74 bool isRealizedImplementation() const;
75 void closeImplementation();
76 bool makeCurrentImplementation();
77 bool releaseContextImplementation();
78 void swapBuffersImplementation();
81 void requestWarpPointer(float x
, float y
);
92 QOpenGLContext
*_glContext
;
93 QOffscreenSurface
*_surface
;
96 GraphicsWindowQt::GraphicsWindowQt(osg::GraphicsContext::Traits
*traits
) :
104 // qDebug() << "GraphicsWindowQt::GraphicsWindowQt";
109 GraphicsWindowQt::~GraphicsWindowQt()
111 // qDebug() << "GraphicsWindowQt::~GraphicsWindowQt";
115 void GraphicsWindowQt::init()
117 // qDebug() << "GraphicsWindowQt::init";
122 // update by WindowData
123 // WindowData* windowData = _traits.get() ? dynamic_cast<WindowData*>(_traits->inheritedWindowData.get()) : 0;
125 // _widget = windowData ? windowData->_widget : NULL;
127 // parent = windowData ? windowData->_parent : NULL;
130 setState(new osg::State
);
131 getState()->setGraphicsContext(this);
133 if (_traits
.valid() && _traits
->sharedContext
.valid()) {
134 getState()->setContextID(_traits
->sharedContext
->getState()->getContextID());
135 incrementContextIDUsageCount(getState()->getContextID());
137 getState()->setContextID(osg::GraphicsContext::createNewContextID());
140 // make sure the event queue has the correct window rectangle size and input range
141 #if OSG_VERSION_GREATER_OR_EQUAL(3, 4, 0)
142 getEventQueue()->syncWindowRectangleWithGraphicsContext();
144 getEventQueue()->syncWindowRectangleWithGraphcisContext();
149 _valid
= _initialized
;
152 bool GraphicsWindowQt::setWindowRectangleImplementation(int x
, int y
, int width
, int height
)
157 void GraphicsWindowQt::getWindowRectangle(int & x
, int & y
, int & width
, int & height
)
160 bool GraphicsWindowQt::setWindowDecorationImplementation(bool windowDecoration
)
165 bool GraphicsWindowQt::getWindowDecoration() const
170 void GraphicsWindowQt::grabFocus()
173 void GraphicsWindowQt::grabFocusIfPointerInWindow()
176 void GraphicsWindowQt::raiseWindow()
179 void GraphicsWindowQt::setWindowName(const std::string
& name
)
182 std::string
GraphicsWindowQt::getWindowName()
187 void GraphicsWindowQt::useCursor(bool cursorOn
)
190 void GraphicsWindowQt::setCursor(MouseCursor cursor
)
193 bool GraphicsWindowQt::valid() const
198 bool GraphicsWindowQt::realizeImplementation()
200 // qDebug() << "GraphicsWindowQt::realizeImplementation";
201 // save the current context
202 // note: this will save only Qt-based contexts
215 QOpenGLContext
*currentContext
= QOpenGLContext::currentContext();
217 if (!currentContext
) {
218 // qDebug() << "GraphicsWindowQt::realizeImplementation - creating owned context";
220 _glContext
= new QOpenGLContext();
221 _glContext
->create();
222 _surface
= new QOffscreenSurface();
223 _surface
->setFormat(_glContext
->format());
226 osgQtQuick::formatInfo(_surface
->format());
229 // qDebug() << "GraphicsWindowQt::realizeImplementation - using current context";
230 _glContext
= currentContext
;
233 //// initialize GL context for the widget
235 // _widget->glInit();
239 bool current
= makeCurrent();
241 // fail if we do not have current context
243 // if ( savedContext )
244 // const_cast< QGLContext* >( savedContext )->makeCurrent();
246 qWarning() << "GraphicsWindowQt::realizeImplementation - can not make context current.";
251 // make sure the event queue has the correct window rectangle size and input range
252 #if OSG_VERSION_GREATER_OR_EQUAL(3, 4, 0)
253 getEventQueue()->syncWindowRectangleWithGraphicsContext();
255 getEventQueue()->syncWindowRectangleWithGraphcisContext();
258 // make this window's context not current
259 // note: this must be done as we will probably make the context current from another thread
260 // and it is not allowed to have one context current in two threads
261 if (!releaseContext()) {
262 qWarning() << "GraphicsWindowQt::realizeImplementation - can not release context.";
265 //// restore previous context
266 // if ( savedContext )
267 // const_cast< QGLContext* >( savedContext )->makeCurrent();
272 bool GraphicsWindowQt::isRealizedImplementation() const
277 void GraphicsWindowQt::runOperations()
279 // While in graphics thread this is last chance to do something useful before
280 // graphics thread will execute its operations.
281 // if (_widget->getNumDeferredEvents() > 0)
282 // _widget->processDeferredEvents();
284 // if (QGLContext::currentContext() != _widget->context())
285 // _widget->makeCurrent();
287 // qDebug() << "GraphicsWindowQt::runOperations";
288 GraphicsWindow::runOperations();
291 bool GraphicsWindowQt::makeCurrentImplementation()
294 qWarning() << "GraphicsWindowQt::makeCurrentImplementation() - no context.";
298 qWarning() << "GraphicsWindowQt::makeCurrentImplementation() - not realized; cannot make current.";
302 if (!_glContext
->makeCurrent(_surface
)) {
303 qWarning() << "GraphicsWindowQt::makeCurrentImplementation : failed to make context current";
307 if (_glContext
!= QOpenGLContext::currentContext()) {
308 qWarning() << "GraphicsWindowQt::makeCurrentImplementation : context is not current";
315 bool GraphicsWindowQt::releaseContextImplementation()
318 qWarning() << "GraphicsWindowQt::releaseContextImplementation() - no context.";
321 if (_glContext
!= QOpenGLContext::currentContext()) {
322 qWarning() << "GraphicsWindowQt::releaseContextImplementation : context is not current";
326 // qDebug() << "GraphicsWindowQt::releaseContextImplementation";
327 _glContext
->doneCurrent();
328 if (_glContext
== QOpenGLContext::currentContext()) {
329 qWarning() << "GraphicsWindowQt::releaseContextImplementation : context is still current";
335 void GraphicsWindowQt::closeImplementation()
337 // qDebug() << "GraphicsWindowQt::closeImplementation";
338 _initialized
= false;
343 // qDebug() << "GraphicsWindowQt::closeImplementation - deleting owned context";
355 void GraphicsWindowQt::swapBuffersImplementation()
357 // _widget->swapBuffers();
359 //// FIXME: the processDeferredEvents should really be executed in a GUI (main) thread context but
360 //// I couln't find any reliable way to do this. For now, lets hope non of *GUI thread only operations* will
361 //// be executed in a QGLWidget::event handler. On the other hand, calling GUI only operations in the
362 //// QGLWidget event handler is an indication of a Qt bug.
363 // if (_widget->getNumDeferredEvents() > 0)
364 // _widget->processDeferredEvents();
366 //// We need to call makeCurrent here to restore our previously current context
367 //// which may be changed by the processDeferredEvents function.
368 // if (QGLContext::currentContext() != _widget->context())
369 // _widget->makeCurrent();
372 void GraphicsWindowQt::requestWarpPointer(float x
, float y
)
375 QtWindowingSystem::QtWindowingSystem()
378 QtWindowingSystem::~QtWindowingSystem()
380 if (osg::Referenced::getDeleteHandler()) {
381 osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0);
382 osg::Referenced::getDeleteHandler()->flushAll();
386 // Return the number of screens present in the system
387 unsigned int QtWindowingSystem::getNumScreens(const osg::GraphicsContext::ScreenIdentifier
& /*si*/)
389 qWarning() << "osgQt: getNumScreens() not implemented yet.";
393 // Return the resolution of specified screen
394 // (0,0) is returned if screen is unknown
395 void QtWindowingSystem::getScreenSettings(const osg::GraphicsContext::ScreenIdentifier
& /*si*/, osg::GraphicsContext::ScreenSettings
& /*resolution*/)
397 qWarning() << "osgQt: getScreenSettings() not implemented yet.";
400 // Set the resolution for given screen
401 bool QtWindowingSystem::setScreenSettings(const osg::GraphicsContext::ScreenIdentifier
& /*si*/, const osg::GraphicsContext::ScreenSettings
& /*resolution*/)
403 qWarning() << "osgQt: setScreenSettings() not implemented yet.";
407 // Enumerates available resolutions
408 void QtWindowingSystem::enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier
& /*screenIdentifier*/, osg::GraphicsContext::ScreenSettingsList
& /*resolution*/)
410 qWarning() << "osgQt: enumerateScreenSettings() not implemented yet.";
413 // Create a graphics context with given traits
414 osg::GraphicsContext
*QtWindowingSystem::createGraphicsContext(osg::GraphicsContext::Traits
*traits
)
416 // if (traits->pbuffer)
418 // OSG_WARN << "osgQt: createGraphicsContext - pbuffer not implemented yet.";
423 osg::ref_ptr
< GraphicsWindowQt
> gc
= new GraphicsWindowQt(traits
);