diff --git a/ApplicationLibCode/ProjectDataModel/Rim3dView.cpp b/ApplicationLibCode/ProjectDataModel/Rim3dView.cpp index 19f00ad9df..2805312a19 100644 --- a/ApplicationLibCode/ProjectDataModel/Rim3dView.cpp +++ b/ApplicationLibCode/ProjectDataModel/Rim3dView.cpp @@ -358,14 +358,11 @@ cvf::Color3f Rim3dView::backgroundColor() const //-------------------------------------------------------------------------------------------------- QWidget* Rim3dView::createViewWidget( QWidget* mainWindowParent ) { - QGLFormat glFormat; - glFormat.setDirectRendering( RiaGuiApplication::instance()->useShaders() ); - // If parent widget is a live widget, the application will get OpenGL window issues if started on a non-primary // screen. Using nullptr as parent solves the issue. // https://github.com/OPM/ResInsight/issues/8192 // - m_viewer = new RiuViewer( glFormat, nullptr ); + m_viewer = new RiuViewer( nullptr ); m_viewer->setOwnerReservoirView( this ); cvf::String xLabel; @@ -537,11 +534,6 @@ QImage Rim3dView::snapshotWindowContent() { if ( m_viewer ) { - // Force update of scheduled display models before snapshotting - RiaViewRedrawScheduler::instance()->updateAndRedrawScheduledViews(); - - m_viewer->repaint(); - return m_viewer->snapshotImage(); } diff --git a/ApplicationLibCode/UserInterface/RiuViewer.cpp b/ApplicationLibCode/UserInterface/RiuViewer.cpp index 00a3d7140e..ea1b8d0ecf 100644 --- a/ApplicationLibCode/UserInterface/RiuViewer.cpp +++ b/ApplicationLibCode/UserInterface/RiuViewer.cpp @@ -27,10 +27,8 @@ #include "RiaPreferences.h" #include "RiaRegressionTestRunner.h" +#include "Rim3dView.h" #include "RimCase.h" -#include "RimGridView.h" -#include "RimProject.h" -#include "RimViewController.h" #include "RimViewLinker.h" #include "RivGridBoxGenerator.h" @@ -60,20 +58,15 @@ #include "cvfCamera.h" #include "cvfFont.h" -#include "cvfOpenGLResourceManager.h" #include "cvfOverlayAxisCross.h" #include "cvfOverlayItem.h" -#include "cvfPartRenderHintCollection.h" -#include "cvfRenderQueueSorter.h" -#include "cvfRenderSequence.h" #include "cvfRendering.h" #include "cvfScene.h" -#include -#include - #include +#include + using cvf::ManipulatorTrackball; const double RI_MIN_NEARPLANE_DISTANCE = 0.1; @@ -92,8 +85,8 @@ std::unique_ptr RiuViewer::s_hoverCursor; //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RiuViewer::RiuViewer( const QGLFormat& format, QWidget* parent ) - : caf::Viewer( format, parent ) +RiuViewer::RiuViewer( QWidget* parent ) + : caf::Viewer( parent ) , m_isNavigationRotationEnabled( true ) , m_zScale( 1.0 ) { diff --git a/ApplicationLibCode/UserInterface/RiuViewer.h b/ApplicationLibCode/UserInterface/RiuViewer.h index 942d39088b..e25aa6c378 100644 --- a/ApplicationLibCode/UserInterface/RiuViewer.h +++ b/ApplicationLibCode/UserInterface/RiuViewer.h @@ -23,15 +23,9 @@ #include "RiuInterfaceToViewWindow.h" #include "RiuViewerToViewInterface.h" -#include "cafFontTools.h" -#include "cafMouseState.h" #include "cafPdmInterfacePointer.h" -#include "cafPdmObject.h" -#include "cafPdmPointer.h" #include "cafViewer.h" -#include "cvfStructGrid.h" - #include class RicCommandFeature; @@ -73,7 +67,7 @@ class RiuViewer : public caf::Viewer, public RiuInterfaceToViewWindow Q_OBJECT public: - RiuViewer( const QGLFormat& format, QWidget* parent ); + RiuViewer( QWidget* parent ); ~RiuViewer() override; RiuViewer( const RiuViewer& ) = delete; diff --git a/Fwk/AppFwk/cafViewer/cafViewer.cpp b/Fwk/AppFwk/cafViewer/cafViewer.cpp index 22ae1b00ae..1652b9b7c1 100644 --- a/Fwk/AppFwk/cafViewer/cafViewer.cpp +++ b/Fwk/AppFwk/cafViewer/cafViewer.cpp @@ -42,16 +42,12 @@ #include "cafPointOfInterestVisualizer.h" #include "cvfCamera.h" -#include "cvfDebugTimer.h" #include "cvfDrawable.h" -#include "cvfDrawableGeo.h" #include "cvfDynamicUniformSet.h" #include "cvfFramebufferObject.h" #include "cvfHitItemCollection.h" -#include "cvfManipulatorTrackball.h" #include "cvfModel.h" #include "cvfOpenGLCapabilities.h" -#include "cvfOpenGLResourceManager.h" #include "cvfOpenGLUtils.h" #include "cvfOverlayImage.h" #include "cvfPart.h" @@ -66,16 +62,18 @@ #include "cvfShaderSourceProvider.h" #include "cvfSingleQuadRenderingGenerator.h" #include "cvfTextureImage.h" -#include "cvfTransform.h" #include "cvfUniform.h" #include "cvfUniformSet.h" +#include "cvfqtOpenGLWidget.h" #include "cvfqtPerformanceInfoHud.h" #include "cvfqtUtils.h" #include #include #include +#include +#include #include @@ -108,14 +106,13 @@ class GlobalViewerDynUniformSet : public cvf::DynamicUniformSet } // namespace caf -std::list caf::Viewer::sm_viewers; cvf::ref caf::Viewer::sm_openGLContextGroup; //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -caf::Viewer::Viewer( const QGLFormat& format, QWidget* parent ) - : caf::OpenGLWidget( contextGroup(), format, nullptr, sharedWidget() ) +caf::Viewer::Viewer( QWidget* parent ) + : cvfqt::OpenGLWidget( contextGroup(), parent ) , m_navigationPolicy( nullptr ) , m_navigationPolicyEnabled( true ) , m_defaultPerspectiveNearPlaneDistance( 0.05 ) @@ -176,12 +173,7 @@ caf::Viewer::Viewer( const QGLFormat& format, QWidget* parent ) m_overlayImage->setBlending( cvf::OverlayImage::TEXTURE_ALPHA ); m_overlayImage->setLayoutFixedPosition( cvf::Vec2i( 0, 0 ) ); - setupMainRendering(); - setupRenderingSequence(); - m_showPerfInfoHud = false; - - sm_viewers.push_back( this ); } //-------------------------------------------------------------------------------------------------- @@ -189,10 +181,6 @@ caf::Viewer::Viewer( const QGLFormat& format, QWidget* parent ) //-------------------------------------------------------------------------------------------------- caf::Viewer::~Viewer() { - this->cvfShutdownOpenGLContext(); - sm_viewers.remove( this ); - - // To delete the layout widget if ( m_layoutWidget ) m_layoutWidget->deleteLater(); } @@ -214,14 +202,6 @@ void caf::Viewer::setupMainRendering() m_mainRendering->addGlobalDynamicUniformSet( m_globalUniformSet.p() ); m_comparisonMainRendering->addGlobalDynamicUniformSet( m_globalUniformSet.p() ); - // Set fixed function rendering if QGLFormat does not support directRendering - if ( !this->format().directRendering() ) - { - m_mainRendering->renderEngine()->enableForcedImmediateMode( true ); - m_comparisonMainRendering->renderEngine()->enableForcedImmediateMode( true ); - m_overlayItemsRendering->renderEngine()->enableForcedImmediateMode( true ); - } - if ( contextGroup()->capabilities() && contextGroup()->capabilities()->hasCapability( cvf::OpenGLCapabilities::FRAMEBUFFER_OBJECT ) ) { @@ -278,14 +258,19 @@ void caf::Viewer::setupRenderingSequence() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -caf::Viewer* caf::Viewer::sharedWidget() +void caf::Viewer::deleteFboOpenGLResources() { - if ( !sm_viewers.empty() ) + // The OpenGL resources can be deleted at any time. CeeViz does not delete resources for FBOs, so delete them manually + + if ( m_offscreenFbo.notNull() ) { - return *( sm_viewers.begin() ); - } + if ( auto context = cvfOpenGLContext() ) + { + context->makeCurrent(); - return nullptr; + m_offscreenFbo->deleteOrReleaseOpenGLResources( context ); + } + } } //-------------------------------------------------------------------------------------------------- @@ -589,21 +574,6 @@ bool caf::Viewer::calculateNearFarPlanes( const cvf::Rendering* rendering, //-------------------------------------------------------------------------------------------------- bool caf::Viewer::event( QEvent* e ) { - // The most reliable way we have found of detecting when an OpenGL context is about to be destroyed is - // hooking into the QEvent::PlatformSurface event and checking for the SurfaceAboutToBeDestroyed event type. - // From the Qt doc: - // The underlying native surface will be destroyed immediately after this event. - // The SurfaceAboutToBeDestroyed event type is useful as a means of stopping rendering to a platform window before - // it is destroyed. - if ( e->type() == QEvent::PlatformSurface ) - { - QPlatformSurfaceEvent* platformSurfaceEvent = static_cast( e ); - if ( platformSurfaceEvent->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed ) - { - cvfShutdownOpenGLContext(); - } - } - if ( e && m_navigationPolicy.notNull() && m_navigationPolicyEnabled ) { switch ( e->type() ) @@ -625,18 +595,14 @@ bool caf::Viewer::event( QEvent* e ) case QEvent::TouchBegin: case QEvent::TouchUpdate: case QEvent::TouchEnd: - if ( m_navigationPolicy->handleInputEvent( static_cast( e ) ) ) - return true; - else - return QGLWidget::event( e ); + if ( m_navigationPolicy->handleInputEvent( static_cast( e ) ) ) return true; break; default: - return QGLWidget::event( e ); break; } } - else - return QGLWidget::event( e ); + + return cvfqt::OpenGLWidget::event( e ); } //-------------------------------------------------------------------------------------------------- @@ -783,10 +749,8 @@ bool caf::Viewer::isPerfInfoHudEnabled() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void caf::Viewer::paintEvent( QPaintEvent* event ) +void caf::Viewer::paintGL() { - makeCurrent(); - cvf::ref myOglContext = cvfOpenGLContext(); CVF_CHECK_OGL( myOglContext.p() ); CVF_ASSERT( myOglContext->isContextValid() ); @@ -886,6 +850,22 @@ void caf::Viewer::paintEvent( QPaintEvent* event ) painter.endNativePainting(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void caf::Viewer::onWidgetOpenGLReady() +{ + setupMainRendering(); + setupRenderingSequence(); + + QOpenGLContext* myQtOpenGLContext = context(); + CVF_ASSERT( myQtOpenGLContext ); + CVF_ASSERT( myQtOpenGLContext->isValid() ); + + // Connect to signal so we get notified when Qt's OpenGL context is about to be destroyed + connect( myQtOpenGLContext, &QOpenGLContext::aboutToBeDestroyed, this, &Viewer::deleteFboOpenGLResources ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -1176,15 +1156,7 @@ void caf::Viewer::updateCachedValuesInScene() //-------------------------------------------------------------------------------------------------- bool caf::Viewer::isShadersSupported() { - QGLFormat::OpenGLVersionFlags flags = QGLFormat::openGLVersionFlags(); - bool hasOpenGL_2_0 = QGLFormat::OpenGL_Version_2_0 & flags; - - if ( hasOpenGL_2_0 ) - { - return true; - } - - return false; + return true; } //-------------------------------------------------------------------------------------------------- @@ -1192,55 +1164,10 @@ bool caf::Viewer::isShadersSupported() //-------------------------------------------------------------------------------------------------- QImage caf::Viewer::snapshotImage() { - // Qt5 : Call paintEvent() manually to make sure invisible widgets are rendered properly - // If this call is skipped, we get an assert in cvf::FramebufferObject::bind() - paintEvent( nullptr ); - - QImage image; - if ( m_offscreenFbo.notNull() && m_offscreenViewportWidth > 0 && m_offscreenViewportHeight > 0 ) - { - cvf::ref myOglContext = cvfOpenGLContext(); - - m_offscreenFbo->bind( myOglContext.p() ); + auto image = grabFramebuffer(); - GLint iOldPackAlignment = 0; - glGetIntegerv( GL_PACK_ALIGNMENT, &iOldPackAlignment ); - glPixelStorei( GL_PACK_ALIGNMENT, 1 ); - CVF_CHECK_OGL( myOglContext.p() ); - - cvf::UByteArray arr( 3 * m_offscreenViewportWidth * m_offscreenViewportHeight ); - - glReadPixels( 0, - 0, - static_cast( m_offscreenViewportWidth ), - static_cast( m_offscreenViewportHeight ), - GL_RGB, - GL_UNSIGNED_BYTE, - arr.ptr() ); - CVF_CHECK_OGL( myOglContext.p() ); - - glPixelStorei( GL_PACK_ALIGNMENT, iOldPackAlignment ); - CVF_CHECK_OGL( myOglContext.p() ); - - cvf::FramebufferObject::useDefaultWindowFramebuffer( myOglContext.p() ); - - cvf::TextureImage texImage; - texImage.setFromRgb( arr.ptr(), m_offscreenViewportWidth, m_offscreenViewportHeight ); - - image = cvfqt::Utils::toQImage( texImage ); - } - else - { - // Code moved from RimView::snapshotWindowContent() - - GLint currentReadBuffer; - glGetIntegerv( GL_READ_BUFFER, ¤tReadBuffer ); - - glReadBuffer( GL_FRONT ); - image = this->grabFrameBuffer(); - - glReadBuffer( currentReadBuffer ); - } + // Convert to RGB32 format to avoid visual artifacts related to alpha channel + image.reinterpretAsFormat( QImage::Format_RGB32 ); return image; } diff --git a/Fwk/AppFwk/cafViewer/cafViewer.h b/Fwk/AppFwk/cafViewer/cafViewer.h index 981745cc4f..36d624f0d0 100644 --- a/Fwk/AppFwk/cafViewer/cafViewer.h +++ b/Fwk/AppFwk/cafViewer/cafViewer.h @@ -36,16 +36,13 @@ #pragma once -#include "cvfAssert.h" -#include "cvfBase.h" #include "cvfCollection.h" #include "cvfObject.h" #include "cvfOpenGL.h" #include "cvfRect.h" -#include "cvfRenderingScissor.h" #include "cvfVector3.h" -#include "cafOpenGLWidget.h" +#include "cvfqtOpenGLWidget.h" namespace cvf { @@ -61,6 +58,7 @@ class Scene; class Texture; class TextureImage; class RayIntersectSpec; +class RenderingScissor; } // namespace cvf namespace caf @@ -79,11 +77,11 @@ namespace caf class GlobalViewerDynUniformSet; class ScissorChanger; -class Viewer : public caf::OpenGLWidget +class Viewer : public cvfqt::OpenGLWidget { Q_OBJECT public: - Viewer( const QGLFormat& format, QWidget* parent ); + Viewer( QWidget* parent ); ~Viewer() override; QWidget* layoutWidget() { return m_layoutWidget; } // Use this when putting it into something @@ -194,6 +192,8 @@ public slots: // Method to override if painting directly on the OpenGl Canvas is needed. virtual void paintOverlayItems( QPainter* painter ){}; + void onWidgetOpenGLReady() override; + // Overridable methods to setup the render system virtual void optimizeClippingPlanes(); @@ -204,7 +204,7 @@ public slots: // Standard overrides. Not for overriding void resizeGL( int width, int height ) override; - void paintEvent( QPaintEvent* event ) override; + void paintGL() override; // Support the navigation policy concept bool event( QEvent* e ) override; @@ -234,6 +234,7 @@ public slots: void updateCamera( int width, int height ); void releaseOGlResourcesForCurrentFrame(); void debugShowRenderingSequencePartNames(); + void deleteFboOpenGLResources(); int clampFrameIndex( int frameIndex ) const; @@ -249,10 +250,8 @@ public slots: void updateOverlayImagePresence(); // System to make sure we share OpenGL resources - static Viewer* sharedWidget(); static cvf::OpenGLContextGroup* contextGroup(); - static std::list sm_viewers; static cvf::ref sm_openGLContextGroup; caf::FrameAnimationControl* m_animationControl;