#279 Use frame buffer objects for snapshots when available, otherwise use grabFrameBuffer()

This commit is contained in:
Magne Sjaastad 2016-08-31 17:34:31 +02:00
parent 457c3c732b
commit 0128baddff
7 changed files with 145 additions and 66 deletions

View File

@ -108,6 +108,8 @@
#ifdef WIN32
#include <fcntl.h>
#endif
#include "RiuSummaryQwtPlot.h"
#include "RiuWellLogPlot.h"
namespace caf
{
@ -1392,6 +1394,43 @@ RiuMainPlotWindow* RiaApplication::mainPlotWindow()
return m_mainPlotWindow;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimViewWindow* RiaApplication::activeViewWindow()
{
RimViewWindow* viewWindow = NULL;
QWidget* topLevelWidget = RiaApplication::activeWindow();
if (dynamic_cast<RiuMainWindow*>(topLevelWidget))
{
viewWindow = RiaApplication::instance()->activeReservoirView();
}
if (dynamic_cast<RiuMainPlotWindow*>(topLevelWidget))
{
RiuMainPlotWindow* mainPlotWindow = dynamic_cast<RiuMainPlotWindow*>(topLevelWidget);
QList<QMdiSubWindow*> subwindows = mainPlotWindow->subWindowList(QMdiArea::StackingOrder);
if (subwindows.size() > 0)
{
RiuSummaryQwtPlot* summaryQwtPlot = dynamic_cast<RiuSummaryQwtPlot*>(subwindows.back()->widget());
if (summaryQwtPlot)
{
viewWindow = summaryQwtPlot->ownerPlotDefinition();
}
RiuWellLogPlot* wellLogPlot = dynamic_cast<RiuWellLogPlot*>(subwindows.back()->widget());
if (wellLogPlot)
{
viewWindow = wellLogPlot->ownerPlotDefinition();
}
}
}
return viewWindow;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -1777,9 +1816,9 @@ void RiaApplication::saveSnapshotAs(const QString& fileName)
//--------------------------------------------------------------------------------------------------
void RiaApplication::copySnapshotToClipboard()
{
QClipboard* clipboard = QApplication::clipboard();
if (clipboard)
{
QClipboard* clipboard = QApplication::clipboard();
if (clipboard)
{
QImage image = grabFrameBufferImage();
if (!image.isNull())
{
@ -2160,21 +2199,26 @@ cvf::Font* RiaApplication::customFont()
//--------------------------------------------------------------------------------------------------
QImage RiaApplication::grabFrameBufferImage()
{
// TODO: Create a general solution that also works with well log plots and summary plots
// For now, only reservoir views are supported by this solution
/*
RimViewWindow* viewWindow = RiaApplication::activeViewWindow();
if (viewWindow)
{
return viewWindow->snapshotWindowContent();
}
return QImage();
*/
QImage image;
if (m_activeReservoirView && m_activeReservoirView->viewer())
{
m_activeReservoirView->viewer()->repaint();
GLint currentReadBuffer;
glGetIntegerv(GL_READ_BUFFER, &currentReadBuffer);
glReadBuffer(GL_FRONT);
image = m_activeReservoirView->viewer()->grabFrameBuffer();
glReadBuffer(currentReadBuffer);
return m_activeReservoirView->snapshotWindowContent();
}
return image;
}
//--------------------------------------------------------------------------------------------------

View File

@ -48,6 +48,7 @@ class RimEclipseView;
class RimProject;
class RimSummaryPlot;
class RimView;
class RimViewWindow;
class RimWellLogPlot;
class RiuMainPlotWindow;
@ -178,6 +179,8 @@ public:
RiuMainPlotWindow* getOrCreateAndShowMainPlotWindow();
RiuMainPlotWindow* mainPlotWindow();
static RimViewWindow* activeViewWindow();
private:
enum ProjectLoadAction
{

View File

@ -20,15 +20,7 @@
#include "RiaApplication.h"
#include "RimSummaryPlot.h"
#include "RimView.h"
#include "RimViewWindow.h"
#include "RimWellLogPlot.h"
#include "RiuMainPlotWindow.h"
#include "RiuMainWindow.h"
#include "RiuSummaryQwtPlot.h"
#include "RiuWellLogPlot.h"
#include <QAction>
#include <QClipboard>
@ -49,34 +41,7 @@ bool RicSnapshotViewToClipboardFeature::isCommandEnabled()
//--------------------------------------------------------------------------------------------------
void RicSnapshotViewToClipboardFeature::onActionTriggered(bool isChecked)
{
RimViewWindow* viewWindow = NULL;
QWidget* topLevelWidget = RiaApplication::activeWindow();
if (dynamic_cast<RiuMainWindow*>(topLevelWidget))
{
viewWindow = RiaApplication::instance()->activeReservoirView();
}
if (dynamic_cast<RiuMainPlotWindow*>(topLevelWidget))
{
RiuMainPlotWindow* mainPlotWindow = dynamic_cast<RiuMainPlotWindow*>(topLevelWidget);
QList<QMdiSubWindow*> subwindows = mainPlotWindow->subWindowList(QMdiArea::StackingOrder);
if (subwindows.size() > 0)
{
RiuSummaryQwtPlot* summaryQwtPlot = dynamic_cast<RiuSummaryQwtPlot*>(subwindows.back()->widget());
if (summaryQwtPlot)
{
viewWindow = summaryQwtPlot->ownerPlotDefinition();
}
RiuWellLogPlot* wellLogPlot = dynamic_cast<RiuWellLogPlot*>(subwindows.back()->widget());
if (wellLogPlot)
{
viewWindow = wellLogPlot->ownerPlotDefinition();
}
}
}
RimViewWindow* viewWindow = RiaApplication::activeViewWindow();
if (viewWindow)
{

View File

@ -255,21 +255,14 @@ void RimView::updateViewerWidget()
//--------------------------------------------------------------------------------------------------
QImage RimView::snapshotWindowContent()
{
QImage image;
if (m_viewer)
{
m_viewer->repaint();
GLint currentReadBuffer;
glGetIntegerv(GL_READ_BUFFER, &currentReadBuffer);
glReadBuffer(GL_FRONT);
image = m_viewer->grabFrameBuffer();
glReadBuffer(currentReadBuffer);
return m_viewer->snapshotImage();
}
return image;
return QImage();
}
//--------------------------------------------------------------------------------------------------

View File

@ -154,6 +154,7 @@ public:
void selectOverlayInfoConfig();
virtual QImage snapshotWindowContent() override;
virtual void zoomAll() override;
@ -197,9 +198,6 @@ protected:
virtual void resetLegendsInViewer() = 0;
virtual void calculateCurrentTotalCellVisibility(cvf::UByteArray* totalVisibility) = 0;
virtual QImage snapshotWindowContent() override;
QPointer<RiuViewer> m_viewer;
caf::PdmField<int> m_currentTimeStep;

View File

@ -46,9 +46,11 @@
#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 "cvfOverlayImage.h"
#include "cvfPart.h"
@ -56,8 +58,11 @@
#include "cvfRayIntersectSpec.h"
#include "cvfRenderQueueSorter.h"
#include "cvfRenderSequence.h"
#include "cvfRenderbufferObject.h"
#include "cvfRendering.h"
#include "cvfScene.h"
#include "cvfShaderSourceProvider.h"
#include "cvfSingleQuadRenderingGenerator.h"
#include "cvfTextureImage.h"
#include "cvfTransform.h"
#include "cvfUniform.h"
@ -184,6 +189,20 @@ void caf::Viewer::setupMainRendering()
m_mainRendering->renderEngine()->enableForcedImmediateMode(true);
}
if (contextGroup()->capabilities() &&
contextGroup()->capabilities()->hasCapability(cvf::OpenGLCapabilities::FRAMEBUFFER_OBJECT))
{
m_offscreenFbo = new cvf::FramebufferObject;
m_mainRendering->setTargetFramebuffer(m_offscreenFbo.p());
cvf::ref<cvf::RenderbufferObject> rbo = new cvf::RenderbufferObject(cvf::RenderbufferObject::DEPTH_COMPONENT24, 1, 1);
m_offscreenFbo->attachDepthRenderbuffer(rbo.p());
m_offscreenTexture = new cvf::Texture(cvf::Texture::TEXTURE_2D, cvf::Texture::RGBA);
m_offscreenTexture->setSize(1, 1);
m_offscreenFbo->attachColorTexture2d(0, m_offscreenTexture.p());
}
updateOverlayImagePresence();
}
@ -192,7 +211,25 @@ void caf::Viewer::setupMainRendering()
//--------------------------------------------------------------------------------------------------
void caf::Viewer::setupRenderingSequence()
{
m_renderingSequence->addRendering(m_mainRendering.p());
m_renderingSequence->addRendering(m_mainRendering.p());
if (m_offscreenFbo.notNull())
{
// Setup second rendering drawing the texture on the screen
// -------------------------------------------------------------------------
cvf::SingleQuadRenderingGenerator quadRenderGen;
cvf::ref<cvf::Sampler> sampler = new cvf::Sampler;
sampler->setWrapMode(cvf::Sampler::CLAMP_TO_EDGE);
sampler->setMinFilter(cvf::Sampler::NEAREST);
sampler->setMagFilter(cvf::Sampler::NEAREST);
quadRenderGen.addTexture(m_offscreenTexture.p(), sampler.p(), "u_texture2D");
quadRenderGen.addFragmentShaderCode(cvf::ShaderSourceProvider::instance()->getSourceFromRepository(cvf::ShaderSourceRepository::fs_Unlit));
quadRenderGen.addFragmentShaderCode(cvf::ShaderSourceProvider::instance()->getSourceFromRepository(cvf::ShaderSourceRepository::src_Texture));
cvf::ref<cvf::Rendering> quadRendering = quadRenderGen.generate();
m_renderingSequence->addRendering(quadRendering.p());
}
updateCamera(width(), height());
}
@ -277,7 +314,6 @@ void caf::Viewer::updateCamera(int width, int height)
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -464,6 +500,16 @@ void caf::Viewer::resizeGL(int width, int height)
{
if (width < 1 || height < 1) return;
if (m_offscreenFbo.notNull())
{
m_offscreenFbo->resizeAttachedBuffers(width, height);
CVF_ASSERT(m_renderingSequence->renderingCount() > 1);
cvf::ref<cvf::Rendering> quadRendering = m_renderingSequence->rendering(1);
quadRendering->camera()->viewport()->set(0, 0, width, height);
}
updateCamera(width, height);
}
@ -476,7 +522,6 @@ void caf::Viewer::enablePerfInfoHud(bool enable)
updateOverlayImagePresence();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -485,8 +530,6 @@ bool caf::Viewer::isPerfInfoHudEnabled()
return m_showPerfInfoHud;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -772,6 +815,32 @@ bool caf::Viewer::isShadersSupported()
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QImage caf::Viewer::snapshotImage()
{
QImage image;
if (m_offscreenTexture.notNull() && m_offscreenTexture->image())
{
image = cvfqt::Utils::toQImage(*(m_offscreenTexture->image()));
}
else
{
// Code moved from RimView::snapshotWindowContent()
GLint currentReadBuffer;
glGetIntegerv(GL_READ_BUFFER, &currentReadBuffer);
glReadBuffer(GL_FRONT);
image = this->grabFrameBuffer();
glReadBuffer(currentReadBuffer);
}
return image;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -49,15 +49,17 @@
namespace cvf {
class Camera;
class FramebufferObject;
class HitItemCollection;
class Model;
class OverlayImage;
class OverlayItem;
class OverlayScalarMapperLegend;
class RenderSequence;
class Rendering;
class Scene;
class Texture;
class TextureImage;
class OverlayItem;
}
namespace caf {
@ -150,6 +152,7 @@ public:
// Find out whether the system supports shaders
static bool isShadersSupported();
QImage snapshotImage();
public slots:
virtual void slotSetCurrentFrame(int frameIndex);
@ -224,6 +227,10 @@ private:
// Parallel projection light modification
cvf::ref<GlobalViewerDynUniformSet> m_globalUniformSet;
// Offscreen render objects
cvf::ref<cvf::FramebufferObject> m_offscreenFbo;
cvf::ref<cvf::Texture> m_offscreenTexture;
};
} // End namespace caf