From a5b0a977e48109cab93f086d872ad32d5fd1b5cf Mon Sep 17 00:00:00 2001 From: Erik Smistad Date: Fri, 4 Apr 2025 14:17:00 +0200 Subject: [PATCH] Replaced deprecated QGLWidget and QGLContext. Tested on linux. --- CMakeLists.txt | 1 + .../SurfaceExtraction/SurfaceExtraction.cpp | 2 +- source/FAST/Data/BoundingBox.cpp | 14 ++--- source/FAST/Data/Image.cpp | 2 +- source/FAST/Data/Mesh.cpp | 12 ++--- source/FAST/DeviceManager.cpp | 8 +-- .../pyfast_and_pyside2_custom_window.py | 5 +- source/FAST/Tools/OpenIGTLinkServer/GUI.cpp | 7 ++- .../FAST/Visualization/ComputationThread.cpp | 7 ++- .../ImagePyramidRenderer.cpp | 16 +++--- .../RenderToImage/RenderToImage.cpp | 20 +++---- .../RenderToImage/RenderToImage.hpp | 4 +- source/FAST/Visualization/Renderer.cpp | 5 +- .../SegmentationRenderer.cpp | 17 +++--- source/FAST/Visualization/View.cpp | 24 ++------- source/FAST/Visualization/View.hpp | 7 ++- source/FAST/Visualization/Window.cpp | 52 +++++++++++++------ source/FAST/Visualization/Window.hpp | 15 +++--- 18 files changed, 112 insertions(+), 106 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 92d4fa791..00f29ab57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -121,6 +121,7 @@ set(CMAKE_CXX_VISIBILITY_PRESET hidden) set(CMAKE_VISIBILITY_INLINES_HIDDEN 1) # This will setup all of FAST's dependencies +add_definitions(-DQT_DISABLE_DEPRECATED_UP_TO=0x050F00) # Make FAST ready for Qt 6 include(cmake/Depdendencies.cmake) if(FAST_BUILD_DOCS) diff --git a/source/FAST/Algorithms/SurfaceExtraction/SurfaceExtraction.cpp b/source/FAST/Algorithms/SurfaceExtraction/SurfaceExtraction.cpp index 9ea490ed1..6006944a0 100644 --- a/source/FAST/Algorithms/SurfaceExtraction/SurfaceExtraction.cpp +++ b/source/FAST/Algorithms/SurfaceExtraction/SurfaceExtraction.cpp @@ -353,7 +353,7 @@ void SurfaceExtraction::execute() { } else { // Transfer OpenCL buffer data to CPU #ifdef FAST_MODULE_VISUALIZATION - QGLFunctions *fun = Window::getMainGLContext()->functions(); + QOpenGLFunctions *fun = Window::getMainGLContext()->functions(); auto data = make_uninitialized_unique(9*totalSum); queue.enqueueReadBuffer( coordinatesBuffer, diff --git a/source/FAST/Data/BoundingBox.cpp b/source/FAST/Data/BoundingBox.cpp index 3608a3a7e..4119a85b0 100644 --- a/source/FAST/Data/BoundingBox.cpp +++ b/source/FAST/Data/BoundingBox.cpp @@ -137,8 +137,8 @@ BoundingBoxSetAccess::pointer BoundingBoxSet::getAccess(accessType type) { if(!QApplication::instance()) { Window::initializeQtApp(); } - if(QGLContext::currentContext() == nullptr) - Window::getMainGLContext()->makeCurrent(); + if(QOpenGLContext::currentContext() == nullptr) + Window::getMainGLContext()->makeCurrent(Window::getQSurface()); QOpenGLFunctions_3_3_Core *fun = new QOpenGLFunctions_3_3_Core; fun->initializeOpenGLFunctions(); @@ -203,9 +203,9 @@ BoundingBoxSetOpenGLAccess::pointer BoundingBoxSet::getOpenGLAccess( if(!QApplication::instance()) { Window::initializeQtApp(); } - if(QGLContext::currentContext() == nullptr) - Window::getMainGLContext()->makeCurrent(); - QGLFunctions *fun = Window::getMainGLContext()->functions(); + if(QOpenGLContext::currentContext() == nullptr) + Window::getMainGLContext()->makeCurrent(Window::getQSurface()); + QOpenGLFunctions *fun = Window::getMainGLContext()->functions(); fun->glDeleteBuffers(1, &mCoordinateVBO); fun->glGenBuffers(1, &mCoordinateVBO); fun->glDeleteBuffers(1, &mLineEBO); @@ -250,7 +250,7 @@ BoundingBoxSetOpenGLAccess::pointer BoundingBoxSet::getOpenGLAccess( } else { if(!mVBODataIsUpToDate) { #ifdef FAST_MODULE_VISUALIZATION - QGLFunctions *fun = Window::getMainGLContext()->functions(); + QOpenGLFunctions *fun = Window::getMainGLContext()->functions(); // Update VBO/EBO data from host // Coordinates fun->glBindBuffer(GL_ARRAY_BUFFER, mCoordinateVBO); @@ -296,7 +296,7 @@ void BoundingBoxSet::freeAll() { // Need mutual exclusive write lock to delete data //VertexBufferObjectAccess::pointer access = getVertexBufferObjectAccess(ACCESS_READ_WRITE); //Window::getMainGLContext()->makeCurrent(); // Need an active context to delete the mesh VBO - QGLFunctions *fun = Window::getMainGLContext()->functions(); + QOpenGLFunctions *fun = Window::getMainGLContext()->functions(); // glDeleteBuffer is not used due to multi-threading issues.. //fun->glDeleteBuffers(1, &mVBOID); diff --git a/source/FAST/Data/Image.cpp b/source/FAST/Data/Image.cpp index d768d6601..53c7d1cb9 100644 --- a/source/FAST/Data/Image.cpp +++ b/source/FAST/Data/Image.cpp @@ -739,7 +739,7 @@ void Image::freeAll() { } if(m_GLtextureID > 0) { // We have to have current GL context to delete it - if(QGLContext::currentContext() == nullptr) { + if(QOpenGLContext::currentContext() == nullptr) { reportWarning() << "Unable to delete texture because no OpenGL context was current" << reportEnd(); } else { glDeleteTextures(1, &m_GLtextureID); diff --git a/source/FAST/Data/Mesh.cpp b/source/FAST/Data/Mesh.cpp index 1fe0e2615..2cce76842 100644 --- a/source/FAST/Data/Mesh.cpp +++ b/source/FAST/Data/Mesh.cpp @@ -123,9 +123,9 @@ VertexBufferObjectAccess::pointer Mesh::getVertexBufferObjectAccess( if(!QApplication::instance()) { Window::initializeQtApp(); } - if(QGLContext::currentContext() == nullptr) - Window::getMainGLContext()->makeCurrent(); - QGLFunctions *fun = Window::getMainGLContext()->functions(); + if(QOpenGLContext::currentContext() == nullptr) + Window::getMainGLContext()->makeCurrent(Window::getQSurface()); + QOpenGLFunctions *fun = Window::getMainGLContext()->functions(); fun->glDeleteBuffers(1, &mCoordinateVBO); fun->glGenBuffers(1, &mCoordinateVBO); if(mHostHasData) { @@ -275,8 +275,8 @@ MeshAccess::pointer Mesh::getMeshAccess(accessType type) { if(!QApplication::instance()) { Window::initializeQtApp(); } - if(QGLContext::currentContext() == nullptr) - Window::getMainGLContext()->makeCurrent(); + if(QOpenGLContext::currentContext() == nullptr) + Window::getMainGLContext()->makeCurrent(Window::getQSurface()); QOpenGLFunctions_3_3_Core *fun = new QOpenGLFunctions_3_3_Core; fun->initializeOpenGLFunctions(); @@ -467,7 +467,7 @@ void Mesh::freeAll() { // Need mutual exclusive write lock to delete data //VertexBufferObjectAccess::pointer access = getVertexBufferObjectAccess(ACCESS_READ_WRITE); //Window::getMainGLContext()->makeCurrent(); // Need an active context to delete the mesh VBO - QGLFunctions *fun = Window::getMainGLContext()->functions(); + QOpenGLFunctions *fun = Window::getMainGLContext()->functions(); // glDeleteBuffer is not used due to multi-threading issues.. //fun->glDeleteBuffers(1, &mVBOID); diff --git a/source/FAST/DeviceManager.cpp b/source/FAST/DeviceManager.cpp index 710cbb5c6..345827d64 100644 --- a/source/FAST/DeviceManager.cpp +++ b/source/FAST/DeviceManager.cpp @@ -90,7 +90,7 @@ std::vector DeviceManager::getDevices(DeviceCriteria crit if(enableVisualization) { #ifdef FAST_MODULE_VISUALIZATION fast::Window::getMainGLContext(); // Still have to create GL context - Window::getMainGLContext()->makeCurrent(); + Window::getMainGLContext()->makeCurrent(nullptr); // If not nullptr here, we get NV-GLX missing on display error #endif #if defined(__APPLE__) || defined(__MACOSX) CGLContextObj appleContext = CGLGetCurrentContext(); @@ -242,8 +242,8 @@ bool DeviceManager::deviceSatisfiesCriteria(OpenCLDevice::pointer device, bool DeviceManager::deviceHasOpenGLInteropCapability(const cl::Device &device, const cl::Platform &platform) { #ifndef _WIN32 if(platform.getInfo().find("NVIDIA") != std::string::npos) { - reportInfo() << "NVIDIA platform was detected on linux, disabling OpenGL interop due to error Xlib extension NV-GLX missing" << reportEnd(); - return false; + //reportInfo() << "NVIDIA platform was detected on linux, disabling OpenGL interop due to error Xlib extension NV-GLX missing" << reportEnd(); + //return false; } #endif // Get the cl_device_id of the device @@ -253,7 +253,7 @@ bool DeviceManager::deviceHasOpenGLInteropCapability(const cl::Device &device, c // Get all devices that are capable of OpenGL interop with this platform // Create properties for CL-GL context #ifdef FAST_MODULE_VISUALIZATION - Window::getMainGLContext()->makeCurrent(); + Window::getMainGLContext()->makeCurrent(Window::getQSurface()); #endif unsigned long* glContext; #if defined(__APPLE__) || defined(__MACOSX) diff --git a/source/FAST/Examples/Python/pyfast_and_pyside2_custom_window.py b/source/FAST/Examples/Python/pyfast_and_pyside2_custom_window.py index afe1b7756..027fd9af2 100644 --- a/source/FAST/Examples/Python/pyfast_and_pyside2_custom_window.py +++ b/source/FAST/Examples/Python/pyfast_and_pyside2_custom_window.py @@ -14,7 +14,6 @@ import PySide2.QtSvg # Must import this before fast due to conflicting symbols import fast # Must import FAST before rest of pyside2 from PySide2.QtWidgets import * -from PySide2.QtOpenGL import QGLWidget from PySide2.QtCore import Slot from shiboken2 import wrapInstance @@ -31,12 +30,12 @@ def __init__(self): # Create FAST view self.view = fast.View() - self.installEventFilter(wrapInstance(int(self.view.asQGLWidget()), QGLWidget)) + self.installEventFilter(wrapInstance(int(self.view.asQGLWidget()), QOpenGLWidget)) self.view.set2DMode() # Create layout and add widgets layout = QVBoxLayout() - layout.addWidget(wrapInstance(int(self.view.asQGLWidget()), QGLWidget)) + layout.addWidget(wrapInstance(int(self.view.asQGLWidget()), QOpenGLWidget)) layout.addWidget(self.button) self.setLayout(layout) diff --git a/source/FAST/Tools/OpenIGTLinkServer/GUI.cpp b/source/FAST/Tools/OpenIGTLinkServer/GUI.cpp index d9e903400..669239243 100644 --- a/source/FAST/Tools/OpenIGTLinkServer/GUI.cpp +++ b/source/FAST/Tools/OpenIGTLinkServer/GUI.cpp @@ -214,15 +214,14 @@ static igtl::ImageMessage::Pointer createIGTLImageMessage(Image::pointer image) void GUI::streamData() { // Hack to make this work on windows (get issues with switching GL context to thread): // 1. Create a new GL context in this thread - QGLWidget* widget = new QGLWidget; - QGLContext* mainGLContext = new QGLContext(QGLFormat::defaultFormat(), widget); // by including widget here the context becomes valid + auto mainGLContext = new QOpenGLContext(); mainGLContext->create(); - if (!mainGLContext->isValid()) { + if(!mainGLContext->isValid()) { throw Exception("Qt GL context is invalid!"); } // 2. Substitute the GL context in the window with this one setMainGLContext(mainGLContext); - mainGLContext->makeCurrent(); + mainGLContext->makeCurrent(nullptr); reportInfo() << "Listening for new connections on port " << mPort << reportEnd(); try { diff --git a/source/FAST/Visualization/ComputationThread.cpp b/source/FAST/Visualization/ComputationThread.cpp index 44996dd27..1f5d7d9c8 100644 --- a/source/FAST/Visualization/ComputationThread.cpp +++ b/source/FAST/Visualization/ComputationThread.cpp @@ -1,7 +1,6 @@ #include "ComputationThread.hpp" #include "SimpleWindow.hpp" #include "View.hpp" -#include #include #include @@ -30,8 +29,8 @@ void ComputationThread::run() { mIsRunning = true; mStop = false; } - QGLContext* mainGLContext = Window::getMainGLContext(); - mainGLContext->makeCurrent(); + auto mainGLContext = Window::getMainGLContext(); + mainGLContext->makeCurrent(Window::getQSurface()); m_signalFinished = true; @@ -216,7 +215,7 @@ QThread* ComputationThread::start() { connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); std::weak_ptr ptr = std::static_pointer_cast(mPtr.lock()); - QGLContext* mainGLContext = Window::getMainGLContext(); + auto mainGLContext = Window::getMainGLContext(); if(!mainGLContext->isValid()) { throw Exception("QGL context is invalid!"); } diff --git a/source/FAST/Visualization/ImagePyramidRenderer/ImagePyramidRenderer.cpp b/source/FAST/Visualization/ImagePyramidRenderer/ImagePyramidRenderer.cpp index 75136402a..a8d7c2bee 100644 --- a/source/FAST/Visualization/ImagePyramidRenderer/ImagePyramidRenderer.cpp +++ b/source/FAST/Visualization/ImagePyramidRenderer/ImagePyramidRenderer.cpp @@ -4,7 +4,6 @@ #include "FAST/Utility.hpp" #include "FAST/SceneGraph.hpp" #include -#include #include #include #include @@ -87,20 +86,21 @@ ImagePyramidRenderer::draw(Matrix4f perspectiveMatrix, Matrix4f viewingMatrix, f if(!m_bufferThread) { // Create thread to load patches // Create a GL context for the thread which is sharing with the context of the view - auto context = new QGLContext(View::getGLFormat(), m_view); - context->create(m_view->context()); + auto context = new QOpenGLContext(m_view); + context->setShareContext(m_view->context()); + context->create(); if(!context->isValid()) throw Exception("The custom Qt GL context is invalid!"); - if(!context->isSharing()) + if(!context->areSharing(context, m_view->context())) throw Exception("The custom Qt GL context is not sharing!"); - context->makeCurrent(); + context->makeCurrent(Window::getQSurface()); #ifdef WIN32 auto nativeContextHandle = wglGetCurrentContext(); context->doneCurrent(); - m_view->context()->makeCurrent(); + m_view->context()->makeCurrent(Window::getQSurface()); auto dc = wglGetCurrentDC(); m_bufferThread = std::make_unique([this, dc, nativeContextHandle]() { @@ -108,7 +108,7 @@ ImagePyramidRenderer::draw(Matrix4f perspectiveMatrix, Matrix4f viewingMatrix, f #elif defined(__APPLE__) auto nativeContextHandle = CGLGetCurrentContext(); context->doneCurrent(); - m_view->context()->makeCurrent(); + m_view->context()->makeCurrent(Window::getQSurface()); m_bufferThread = std::make_unique([this, nativeContextHandle]() { CGLSetCurrentContext(nativeContextHandle); @@ -117,7 +117,7 @@ ImagePyramidRenderer::draw(Matrix4f perspectiveMatrix, Matrix4f viewingMatrix, f auto drawable = glXGetCurrentDrawable(); auto display = glXGetCurrentDisplay(); context->doneCurrent(); - m_view->context()->makeCurrent(); + m_view->context()->makeCurrent(Window::getQSurface()); m_bufferThread = std::make_unique([this, display, drawable, nativeContextHandle]() { glXMakeCurrent(display, drawable, nativeContextHandle); diff --git a/source/FAST/Visualization/RenderToImage/RenderToImage.cpp b/source/FAST/Visualization/RenderToImage/RenderToImage.cpp index efb9f35ec..ee7bda698 100644 --- a/source/FAST/Visualization/RenderToImage/RenderToImage.cpp +++ b/source/FAST/Visualization/RenderToImage/RenderToImage.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include namespace fast { @@ -23,22 +23,24 @@ RenderToImage::RenderToImage(Color bgcolor, int width, int height) { if(QThread::currentThread() == QApplication::instance()->thread()) { // Is main thread? // Main thread.. - QGLContext *context = new QGLContext(View::getGLFormat(), fast::Window::getSecondaryGLContext()->device()); - context->create(fast::Window::getSecondaryGLContext()); - if(!context->isValid() || !context->isSharing()) { + auto context = new QOpenGLContext(); + context->setShareContext(fast::Window::getSecondaryGLContext()); + context->create(); + if(!context->isValid() || !context->areSharing(context, fast::Window::getSecondaryGLContext())) { throw Exception("The custom Qt GL context in fast::View is invalid!"); } m_context = context; } else { // Computation thread - QGLContext *context = new QGLContext(View::getGLFormat(), fast::Window::getMainGLContext()->device()); - context->create(fast::Window::getMainGLContext()); - if(!context->isValid() || !context->isSharing()) { + auto context = new QOpenGLContext(); + context->setShareContext(fast::Window::getMainGLContext()); + context->create(); + if(!context->isValid() || !context->areSharing(context, fast::Window::getMainGLContext())) { throw Exception("The custom Qt GL context in fast::View is invalid!"); } m_context = context; } - m_context->makeCurrent(); + m_context->makeCurrent(Window::getQSurface()); initializeOpenGLFunctions(); } @@ -81,7 +83,7 @@ std::vector RenderToImage::getRenderers() { } void RenderToImage::execute() { - m_context->makeCurrent(); + m_context->makeCurrent(Window::getQSurface()); bool doContinue = true; for(auto renderer : getRenderers()) { renderer->update(m_executeToken); diff --git a/source/FAST/Visualization/RenderToImage/RenderToImage.hpp b/source/FAST/Visualization/RenderToImage/RenderToImage.hpp index db88eed6c..d99a0e60d 100644 --- a/source/FAST/Visualization/RenderToImage/RenderToImage.hpp +++ b/source/FAST/Visualization/RenderToImage/RenderToImage.hpp @@ -4,7 +4,7 @@ #include #include -class QGLContext; +class QOpenGLContext; namespace fast { @@ -77,7 +77,7 @@ class FAST_EXPORT RenderToImage : public ProcessObject, protected QOpenGLFunctio float mLeft, mRight, mBottom, mTop; // Used for ortho projection - QGLContext* m_context; + QOpenGLContext* m_context; protected: void recalculateCamera(); void getMinMaxFromBoundingBoxes(bool transform, Vector3f& min, Vector3f& max); diff --git a/source/FAST/Visualization/Renderer.cpp b/source/FAST/Visualization/Renderer.cpp index a6bb08126..c6721e2f5 100644 --- a/source/FAST/Visualization/Renderer.cpp +++ b/source/FAST/Visualization/Renderer.cpp @@ -97,8 +97,9 @@ DataBoundingBox Renderer::getBoundingBox(bool transform) { void Renderer::createShaderProgram(std::vector shaderFilenames, std::string programName) { // We need an active GL context to do this, and we also need to initialize the OpenGLFunctions // First check if an there is an active GL context - if(QGLContext::currentContext() == nullptr) - Window::getMainGLContext()->makeCurrent(); + if(QOpenGLContext::currentContext() == nullptr) { + Window::getMainGLContext()->makeCurrent(Window::getQSurface()); + } initializeOpenGLFunctions(); uint programID = glCreateProgram(); diff --git a/source/FAST/Visualization/SegmentationRenderer/SegmentationRenderer.cpp b/source/FAST/Visualization/SegmentationRenderer/SegmentationRenderer.cpp index bccc95685..efb1b35ad 100644 --- a/source/FAST/Visualization/SegmentationRenderer/SegmentationRenderer.cpp +++ b/source/FAST/Visualization/SegmentationRenderer/SegmentationRenderer.cpp @@ -1,8 +1,8 @@ #ifdef FAST_MODULE_WSI #include +#include #endif #include "SegmentationRenderer.hpp" -#include #include #ifdef WIN32 #elif defined(__APPLE__) || defined(__MACOSX) @@ -136,20 +136,21 @@ void SegmentationRenderer::drawPyramid(std::shared_ptr dataTo if(!m_bufferThread) { // Create thread to load patches // Create a GL context for the thread which is sharing with the context of the view - auto context = new QGLContext(View::getGLFormat(), m_view); - context->create(m_view->context()); + auto context = new QOpenGLContext(m_view); + context->setShareContext(m_view->context()); + context->create(); if(!context->isValid()) throw Exception("The custom Qt GL context is invalid!"); - if(!context->isSharing()) + if(!context->areSharing(context, m_view->context())) throw Exception("The custom Qt GL context is not sharing!"); - context->makeCurrent(); + context->makeCurrent(Window::getQSurface()); #ifdef WIN32 auto nativeContextHandle = wglGetCurrentContext(); context->doneCurrent(); - m_view->context()->makeCurrent(); + m_view->context()->makeCurrent(Window::getQSurface()); auto dc = wglGetCurrentDC(); m_bufferThread = std::make_unique([this, dc, nativeContextHandle]() { @@ -157,7 +158,7 @@ void SegmentationRenderer::drawPyramid(std::shared_ptr dataTo #elif defined(__APPLE__) auto nativeContextHandle = CGLGetCurrentContext(); context->doneCurrent(); - m_view->context()->makeCurrent(); + m_view->context()->makeCurrent(Window::getQSurface()); m_bufferThread = std::make_unique([this, nativeContextHandle]() { CGLSetCurrentContext(nativeContextHandle); @@ -166,7 +167,7 @@ void SegmentationRenderer::drawPyramid(std::shared_ptr dataTo auto drawable = glXGetCurrentDrawable(); auto display = glXGetCurrentDisplay(); context->doneCurrent(); - m_view->context()->makeCurrent(); + m_view->context()->makeCurrent(Window::getQSurface()); m_bufferThread = std::make_unique([this, display, drawable, nativeContextHandle]() { glXMakeCurrent(display, drawable, nativeContextHandle); diff --git a/source/FAST/Visualization/View.cpp b/source/FAST/Visualization/View.cpp index 378fea2ac..76ce6898c 100644 --- a/source/FAST/Visualization/View.cpp +++ b/source/FAST/Visualization/View.cpp @@ -51,13 +51,6 @@ void View::setBackgroundColor(Color color) { mBackgroundColor = color; } -QGLFormat View::getGLFormat() { - QGLFormat qglFormat = QGLFormat::defaultFormat(); - qglFormat.setVersion(3, 3); - qglFormat.setProfile(QGLFormat::CoreProfile); - return qglFormat; -} - View::View() { createInputPort(0, false); @@ -83,19 +76,13 @@ View::View() { timer = new QTimer(this); timer->start(1000 / mFramerate); // in milliseconds timer->setSingleShot(false); - QObject::connect(timer, SIGNAL(timeout()), this, SLOT(updateGL())); + QObject::connect(timer, SIGNAL(timeout()), this, SLOT(update())); m_textRenderer = TextRenderer::create(42, Color::Black(), TextRenderer::STYLE_NORMAL, TextRenderer::POSITION_BOTTOM_LEFT); m_lineRenderer = LineRenderer::create(); if(QThread::currentThread() != QApplication::instance()->thread()) { throw Exception("FAST View must be created in the main thread"); } - QGLContext *context = new QGLContext(getGLFormat(), this); - context->create(fast::Window::getSecondaryGLContext()); - this->setContext(context); - if(!context->isValid() || !context->isSharing()) { - throw Exception("The custom Qt GL context in fast::View is invalid!"); - } } void View::loadAttributes() { @@ -525,7 +512,6 @@ void View::initializeGL() { void View::paintGL() { - mRuntimeManager->startRegularTimer("paint"); if(!mIsIn2DMode && !mVolumeRenderers.empty()) @@ -742,12 +728,12 @@ void View::wheelEvent(QWheelEvent *event) { float currentPosX = (event->position().x()/width())*(mRight - mLeft) + mLeft; float currentPosY = (event->position().y()/height())*(mTop - mBottom) + mBottom; // First: Zoom towards center - if(event->delta() > 0) { + if(event->angleDelta().y() > 0) { mLeft = mLeft + targetSizeX*0.5f; mRight = mRight - targetSizeX*0.5f; mBottom = mBottom + targetSizeY * 0.5f; mTop = mTop - targetSizeY*0.5f; - } else if(event->delta() < 0) { + } else if(event->angleDelta().y() < 0) { mLeft = mLeft - targetSizeX * 0.5f;; mRight = mRight + targetSizeX*0.5f; mBottom = mBottom - targetSizeY*0.5f; @@ -765,10 +751,10 @@ void View::wheelEvent(QWheelEvent *event) { mPerspectiveMatrix = loadOrthographicMatrix(mLeft * scalingWidth, mRight * scalingWidth, mBottom * scalingHeight, mTop * scalingHeight, zNear, zFar); } else { - if(event->delta() > 0) { + if(event->angleDelta().y() > 0) { mCameraPosition[2] += (zFar - zNear) * 0.05f; m3DViewingTransformation.pretranslate(Vector3f(0, 0, (zFar - zNear) * 0.05f)); - } else if(event->delta() < 0) { + } else if(event->angleDelta().y() < 0) { mCameraPosition[2] += -(zFar - zNear) * 0.05f; m3DViewingTransformation.pretranslate(Vector3f(0, 0, -(zFar - zNear) * 0.05f)); } diff --git a/source/FAST/Visualization/View.hpp b/source/FAST/Visualization/View.hpp index 84aa8d541..dbf48c089 100644 --- a/source/FAST/Visualization/View.hpp +++ b/source/FAST/Visualization/View.hpp @@ -4,7 +4,7 @@ #include "Renderer.hpp" #include "Plane.hpp" #include -#include +#include #include #include #include @@ -15,7 +15,7 @@ namespace fast { class TextRenderer; class ComputationThread; -class FAST_EXPORT View : public QGLWidget, public ProcessObject, protected QOpenGLFunctions_3_3_Core { +class FAST_EXPORT View : public QOpenGLWidget, public ProcessObject, protected QOpenGLFunctions_3_3_Core { //FAST_OBJECT(View) Q_OBJECT public: @@ -48,7 +48,6 @@ class FAST_EXPORT View : public QGLWidget, public ProcessObject, protected QOpe }; View(); std::vector getRenderers(); - static QGLFormat getGLFormat(); Matrix4f getViewMatrix() const; Matrix4f getPerspectiveMatrix() const; void loadAttributes() override; @@ -57,7 +56,7 @@ class FAST_EXPORT View : public QGLWidget, public ProcessObject, protected QOpe Level 0.5 makes images in the view half its size. Level 2 makes images in the view double in size. */ void setZoom(float zoom); - QGLWidget* asQGLWidget() { return (QGLWidget*)this; } + QOpenGLWidget* asQGLWidget() { return (QOpenGLWidget*)this; } /** * @brief Enable or disable scalebar * @param enable diff --git a/source/FAST/Visualization/Window.cpp b/source/FAST/Visualization/Window.cpp index d403d69bc..0a0f7824c 100644 --- a/source/FAST/Visualization/Window.cpp +++ b/source/FAST/Visualization/Window.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #ifndef WIN32 #ifndef __APPLE__ #include @@ -15,8 +16,9 @@ namespace fast { -QGLContext* Window::mMainGLContext = nullptr; // Lives in main thread or computation thread if it exists. -QGLContext* Window::mSecondaryGLContext = nullptr; // Lives in main thread always +QOpenGLContext* Window::mMainGLContext = nullptr; // Lives in main thread or computation thread if it exists. +QOpenGLContext* Window::mSecondaryGLContext = nullptr; // Lives in main thread always +QOffscreenSurface* Window::m_offscreenSurface = nullptr; class FAST_EXPORT FASTApplication : public QApplication { public: @@ -165,6 +167,15 @@ void Window::initializeQtApp() { // Create some dummy argc and argv options as QApplication requires it int* argc = new int[1]; *argc = 0; + + QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts); + + // Set default OpenGL format for all GL contexts to use: + QSurfaceFormat qglFormat = QSurfaceFormat::defaultFormat(); + qglFormat.setVersion(3, 3); + qglFormat.setProfile(QSurfaceFormat::CoreProfile); + QSurfaceFormat::setDefaultFormat(qglFormat); + #if defined(WIN32) || defined(__APPLE__) QApplication* app = new FASTApplication(*argc,NULL); #else @@ -200,22 +211,20 @@ void Window::initializeQtApp() { } // Create computation GL context, if it doesn't exist - if(mMainGLContext == NULL && Config::getVisualization()) { + if(mMainGLContext == nullptr && Config::getVisualization()) { Reporter::info() << "Creating new GL context for computation thread" << Reporter::end(); // Create GL context to be shared with the CL contexts - QGLWidget* widget = new QGLWidget; - mMainGLContext = new QGLContext(View::getGLFormat(), widget); // by including widget here the context becomes valid + m_offscreenSurface = new QOffscreenSurface; + m_offscreenSurface->create(); + if(!m_offscreenSurface->isValid()) + throw Exception("QOffscreenSurface was invalid"); + mMainGLContext = new QOpenGLContext(); // by including widget here the context becomes valid + mMainGLContext->setShareContext(QOpenGLContext::globalShareContext()); mMainGLContext->create(); - mSecondaryGLContext = new QGLContext(View::getGLFormat(), widget); // by including widget here the context becomes valid - mSecondaryGLContext->create(mMainGLContext); - /* - // Do this by creating an offscreen GL context using a dummy QGLPixelBuffer - // TODO this is not working for some.. why? - auto buffer = new QGLPixelBuffer(8,8, View::getGLFormat()); - buffer->makeCurrent(); - mMainGLContext = buffer->context(); - */ + mSecondaryGLContext = new QOpenGLContext(); // by including widget here the context becomes valid + mSecondaryGLContext->setShareContext(mMainGLContext); + mSecondaryGLContext->create(); if(!mMainGLContext->isValid()) { throw Exception("Qt GL context is invalid!"); } @@ -333,7 +342,7 @@ void Window::setTimeout(unsigned int milliseconds) { mTimeout = milliseconds; } -QGLContext* Window::getMainGLContext() { +QOpenGLContext* Window::getMainGLContext() { if(mMainGLContext == nullptr) { if(!Config::getVisualization()) throw Exception("Visualization in FAST was disabled, unable to continue.\nIf you want to run FAST with visualization on a remote server, see the wiki page\nhttps://github.com/smistad/FAST/wiki/Running-FAST-on-a-remote-server"); @@ -343,7 +352,7 @@ QGLContext* Window::getMainGLContext() { return mMainGLContext; } -QGLContext* Window::getSecondaryGLContext() { +QOpenGLContext* Window::getSecondaryGLContext() { if(mSecondaryGLContext == nullptr) { if(!Config::getVisualization()) throw Exception("Visualization in FAST was disabled, unable to continue.\nIf you want to run FAST with visualization on a remote server, see the wiki page\nhttps://github.com/smistad/FAST/wiki/Running-FAST-on-a-remote-server"); @@ -355,7 +364,7 @@ QGLContext* Window::getSecondaryGLContext() { -void Window::setMainGLContext(QGLContext* context) { +void Window::setMainGLContext(QOpenGLContext* context) { mMainGLContext = context; } @@ -496,4 +505,13 @@ void Window::setCenterLayout(QLayout *layout) { m_mainVLayout->insertLayout(1, layout); } +QSurface *Window::getQSurface() { + if(mMainGLContext == nullptr) { + if(!Config::getVisualization()) + throw Exception("Visualization in FAST was disabled, unable to continue.\nIf you want to run FAST with visualization on a remote server, see the wiki page\nhttps://github.com/smistad/FAST/wiki/Running-FAST-on-a-remote-server"); + initializeQtApp(); + } + return (QSurface*)m_offscreenSurface; +} + } // end namespace fast diff --git a/source/FAST/Visualization/Window.hpp b/source/FAST/Visualization/Window.hpp index d40fddb37..2d96baa21 100644 --- a/source/FAST/Visualization/Window.hpp +++ b/source/FAST/Visualization/Window.hpp @@ -6,13 +6,12 @@ #include "ComputationThread.hpp" #include "View.hpp" #include -#include -class QGLContext; class QEventLoop; class QVBoxLayout; class QHBoxLayout; class QOffscreenSurface; +class QOpenGLContext; namespace fast { @@ -38,9 +37,9 @@ class FAST_EXPORT Window : public QObject, public AttributeObject { Q_OBJECT public: static void initializeQtApp(); - static QGLContext* getMainGLContext(); - static QGLContext* getSecondaryGLContext(); - static void setMainGLContext(QGLContext* context); + static QOpenGLContext* getMainGLContext(); + static QOpenGLContext* getSecondaryGLContext(); + static void setMainGLContext(QOpenGLContext* context); /** * Makes the window close after a specific number of ms */ @@ -112,6 +111,7 @@ class FAST_EXPORT Window : public QObject, public AttributeObject { std::string getNameOfClass() { return "Window"; } + static QSurface* getQSurface(); protected: void startComputationThread(); void stopComputationThread(); @@ -136,8 +136,9 @@ class FAST_EXPORT Window : public QObject, public AttributeObject { void setCenterWidget(QWidget* widget); void setCenterLayout(QLayout* layout); private: - static QGLContext* mMainGLContext; - static QGLContext* mSecondaryGLContext; + static QOpenGLContext* mMainGLContext; + static QOpenGLContext* mSecondaryGLContext; + static QOffscreenSurface* m_offscreenSurface; public Q_SLOTS: void stop();