From Robert Milharcic, "This will hopefully fix some issues with osgQt, more precisely with GLWidget event handling. There are at least two current GL context braking events, QEvent::Hide and QEvent::ParentChange. When running in a multithreaded mode they both try to change current GL context in a wrong thread (main GUI thread). The QEvent::ParentChange is also problematic when running in a single threaded model because Qt is going to release current contex then delete it, and then it will create new one, and as a result the osg will continue to render to an invalid deleted context. This changes workaround above problems by deferring execution of the problematic evens. These events has to be enqueued and executed later. The enqueued event processing is currently done right after swap in a swapBuffersImplementation of GraphicsWindowQt while code is running in a render thread by calling QGLWidget handler directly. In principle the deferred events queue should be executed while in GUI thread but I couldn't find any reliable way to do this, that is without risking a deadlock. For now it is assumed, Qt is not going to execute any GUI thread only operations inside the QGLWidget handler."

This commit is contained in:
Robert Osfield
2011-09-13 11:09:39 +00:00
parent 098bc6df5e
commit 64fa6aec43
3 changed files with 133 additions and 20 deletions

View File

@@ -261,7 +261,7 @@ class OSG_EXPORT GraphicsContext : public Object
void removeAllOperations();
/** Run the operations. */
void runOperations();
virtual void runOperations();
typedef std::list< ref_ptr<Operation> > GraphicsOperationQueue;

View File

@@ -14,8 +14,13 @@
#ifndef OSGVIEWER_GRAPHICSWINDOWQT
#define OSGVIEWER_GRAPHICSWINDOWQT
#include <osgViewer/GraphicsWindow>
#include <QtCore/QMutex>
#include <QtCore/QEvent>
#include <QtCore/QQueue>
#include <QtCore/QSet>
#include <QtOpenGL/QGLWidget>
#include <osgViewer/GraphicsWindow>
#include <osgQt/Export>
class QInputEvent;
@@ -46,6 +51,7 @@ void OSGQT_EXPORT setViewer( osgViewer::ViewerBase *viewer );
class OSGQT_EXPORT GLWidget : public QGLWidget
{
typedef QGLWidget inherited;
public:
GLWidget( QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0, bool forwardKeyEvents = false );
@@ -71,9 +77,37 @@ public:
virtual void wheelEvent( QWheelEvent* event );
protected:
int getNumDeferredEvents()
{
QMutexLocker lock(&_deferredEventQueueMutex);
return _deferredEventQueue.count();
}
void enqueueDeferredEvent(QEvent::Type eventType, QEvent::Type removeEventType = QEvent::None)
{
QMutexLocker lock(&_deferredEventQueueMutex);
if (removeEventType != QEvent::None)
{
if (_deferredEventQueue.removeOne(removeEventType))
_eventCompressor.remove(eventType);
}
if (_eventCompressor.find(eventType) == _eventCompressor.end())
{
_deferredEventQueue.enqueue(eventType);
_eventCompressor.insert(eventType);
}
}
void processDeferredEvents();
friend class GraphicsWindowQt;
GraphicsWindowQt* _gw;
QMutex _deferredEventQueueMutex;
QQueue<QEvent::Type> _deferredEventQueue;
QSet<QEvent::Type> _eventCompressor;
bool _forwardKeyEvents;
virtual void resizeEvent( QResizeEvent* event );
@@ -96,8 +130,8 @@ public:
inline GLWidget* getGraphWidget() { return _widget; }
/// deprecated
inline const GLWidget* getGraphWidget() const { return _widget; }
struct WindowData : public osg::Referenced
struct WindowData : public osg::Referenced
{
WindowData( GLWidget* widget = NULL, GLWidget* parent = NULL ): _widget(widget), _parent(parent) {}
GLWidget* _widget;
@@ -129,12 +163,13 @@ struct WindowData : public osg::Referenced
virtual bool makeCurrentImplementation();
virtual bool releaseContextImplementation();
virtual void swapBuffersImplementation();
virtual void runOperations();
virtual void requestWarpPointer( float x, float y );
protected:
friend class GLWidget;
friend class GLWidget;
GLWidget* _widget;
bool _ownsWidget;
QCursor _currentCursor;