Skip to content

Commit

Permalink
Use modern OpenGL Qt widget
Browse files Browse the repository at this point in the history
Use cvfqt::OpenGLWidget and make required changes
- move code from paintEvent to paintGL to make grabFrambuffer work
- remove obsolete sharedWidget
- implement onWidgetOpenGLReady and initialize rendering in this function as OpenGL capabilities is required
- simplify snapshotImage to use grabFramebuffer

Fix missing include
  • Loading branch information
magnesj committed Feb 7, 2024
1 parent 6ce9af1 commit 8e13d6c
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 149 deletions.
10 changes: 1 addition & 9 deletions ApplicationLibCode/ProjectDataModel/Rim3dView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
}

Expand Down
17 changes: 5 additions & 12 deletions ApplicationLibCode/UserInterface/RiuViewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 <QLabel>
#include <QMouseEvent>

#include <algorithm>

#include <QLabel>

using cvf::ManipulatorTrackball;

const double RI_MIN_NEARPLANE_DISTANCE = 0.1;
Expand All @@ -92,8 +85,8 @@ std::unique_ptr<QCursor> 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 )
{
Expand Down
8 changes: 1 addition & 7 deletions ApplicationLibCode/UserInterface/RiuViewer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <memory>

class RicCommandFeature;
Expand Down Expand Up @@ -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;
Expand Down
151 changes: 39 additions & 112 deletions Fwk/AppFwk/cafViewer/cafViewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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 <QDebug>
#include <QHBoxLayout>
#include <QInputEvent>
#include <QOpenGLContext>
#include <QPainter>

#include <cmath>

Expand Down Expand Up @@ -108,14 +106,13 @@ class GlobalViewerDynUniformSet : public cvf::DynamicUniformSet

} // namespace caf

std::list<caf::Viewer*> caf::Viewer::sm_viewers;
cvf::ref<cvf::OpenGLContextGroup> 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 )
Expand Down Expand Up @@ -176,23 +173,14 @@ 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 );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::Viewer::~Viewer()
{
this->cvfShutdownOpenGLContext();
sm_viewers.remove( this );

// To delete the layout widget
if ( m_layoutWidget ) m_layoutWidget->deleteLater();
}

Expand All @@ -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 ) )
{
Expand Down Expand Up @@ -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 );
}
}
}

//--------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -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<QPlatformSurfaceEvent*>( e );
if ( platformSurfaceEvent->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed )
{
cvfShutdownOpenGLContext();
}
}

if ( e && m_navigationPolicy.notNull() && m_navigationPolicyEnabled )
{
switch ( e->type() )
Expand All @@ -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<QInputEvent*>( e ) ) )
return true;
else
return QGLWidget::event( e );
if ( m_navigationPolicy->handleInputEvent( static_cast<QInputEvent*>( e ) ) ) return true;
break;
default:
return QGLWidget::event( e );
break;
}
}
else
return QGLWidget::event( e );

return cvfqt::OpenGLWidget::event( e );
}

//--------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -783,10 +749,8 @@ bool caf::Viewer::isPerfInfoHudEnabled()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void caf::Viewer::paintEvent( QPaintEvent* event )
void caf::Viewer::paintGL()
{
makeCurrent();

cvf::ref<cvf::OpenGLContext> myOglContext = cvfOpenGLContext();
CVF_CHECK_OGL( myOglContext.p() );
CVF_ASSERT( myOglContext->isContextValid() );
Expand Down Expand Up @@ -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 );
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -1176,71 +1156,18 @@ 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;
}

//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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<cvf::OpenGLContext> 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<GLsizei>( m_offscreenViewportWidth ),
static_cast<GLsizei>( 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, &currentReadBuffer );

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;
}
Expand Down
Loading

0 comments on commit 8e13d6c

Please sign in to comment.