Commit e734212b authored by Christian Schulte zu Berge's avatar Christian Schulte zu Berge
Browse files

Renamed CampvisPainter to PipelinePainter. The PipelinePainter now directly...

Renamed CampvisPainter to PipelinePainter. The PipelinePainter now directly belongs to the corresponding AbstractPipeline, which also owns the pointer and takes care of creating, (de-)initializing and destroying it.
parent a916097f
......@@ -35,7 +35,6 @@
#include "cgt/texturereadertga.h"
#include "cgt/qt/qtthreadedcanvas.h"
#include "application/campvispainter.h"
#include "application/gui/properties/propertywidgetfactory.h"
#include "application/gui/mainwindow.h"
#include "application/gui/mdi/mdidockablewindow.h"
......@@ -45,6 +44,7 @@
#include "core/tools/quadrenderer.h"
#include "core/pipeline/abstractpipeline.h"
#include "core/pipeline/abstractworkflow.h"
#include "core/pipeline/pipelinepainter.h"
#include "core/datastructures/imagerepresentationconverter.h"
#include "core/pipeline/visualizationprocessor.h"
......@@ -218,8 +218,8 @@ namespace campvis {
cgtAssert(_initialized, "Tried to deinitialize uninitialized CampVisApplication.");
// Stop all pipeline threads.
for (std::vector<PipelineRecord>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
it->_pipeline->stop();
for (auto it = _pipelines.begin(); it != _pipelines.end(); ++it) {
(*it)->stop();
}
for (auto it = _workflows.begin(); it != _workflows.end(); ++it)
......@@ -232,9 +232,8 @@ namespace campvis {
delete _errorTexture;
// Deinit pipeline and painter first
for (std::vector<PipelineRecord>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
it->_pipeline->deinit();
it->_painter->deinit();
for (auto it = _pipelines.begin(); it != _pipelines.end(); ++it) {
(*it)->deinit();
}
_mainWindow->deinit();
......@@ -242,11 +241,10 @@ namespace campvis {
}
// now delete everything in the right order:
for (std::vector<PipelineRecord>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
delete it->_painter;
delete it->_pipeline;
for (auto it = _pipelines.begin(); it != _pipelines.end(); ++it) {
delete *it;
}
for (std::vector<DataContainer*>::iterator it = _dataContainers.begin(); it != _dataContainers.end(); ++it) {
for (auto it = _dataContainers.begin(); it != _dataContainers.end(); ++it) {
delete *it;
}
......@@ -291,14 +289,10 @@ namespace campvis {
cgt::QtThreadedCanvas* canvas = new cgt::QtThreadedCanvas("CAMPVis", cgt::ivec2(512, 512));
canvas->init();
CampVisPainter* painter = new CampVisPainter(canvas, pipeline);
canvas->setPainter(painter, false);
pipeline->setCanvas(canvas);
painter->setErrorTexture(_errorTexture);
PipelineRecord pr = { pipeline, painter };
_pipelines.push_back(pr);
pipeline->getPipelinePainter()->setErrorTexture(_errorTexture);
_pipelines.push_back(pipeline);
_pipelineWindows[pipeline] = _mainWindow->addVisualizationPipelineWidget(name, canvas);
// initialize context (GLEW) and pipeline in OpenGL thread)
......@@ -362,8 +356,8 @@ namespace campvis {
LINFO("Rebuilding shaders from file successful.");
}
for (std::vector<PipelineRecord>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
for (std::vector<AbstractProcessor*>::const_iterator pit = it->_pipeline->getProcessors().begin(); pit != it->_pipeline->getProcessors().end(); ++pit) {
for (auto it = _pipelines.begin(); it != _pipelines.end(); ++it) {
for (auto pit = (*it)->getProcessors().cbegin(); pit != (*it)->getProcessors().cend(); ++pit) {
if (VisualizationProcessor* tester = dynamic_cast<VisualizationProcessor*>(*pit)) {
tester->invalidate(AbstractProcessor::INVALID_RESULT);
}
......
......@@ -50,7 +50,6 @@ namespace campvis {
class AbstractPipeline;
class AbstractWorkflow;
class MainWindow;
class CampVisPainter;
class MdiDockableWindow;
class LuaVmState;
......@@ -70,12 +69,6 @@ namespace campvis {
friend class MainWindow;
public:
/// Record storing a pipeline together with its painter and Lua VM state.
struct PipelineRecord {
AbstractPipeline* _pipeline;
CampVisPainter* _painter;
};
/**
* Creates a new CampVisApplication.
* \param argc number of passed arguments
......@@ -167,7 +160,7 @@ namespace campvis {
std::vector<AbstractWorkflow*> _workflows;
/// All pipelines
std::vector<PipelineRecord> _pipelines;
std::vector<AbstractPipeline*> _pipelines;
/// Map of all pipelines with their MDI windows
std::map<AbstractPipeline*, MdiDockableWindow*> _pipelineWindows;
......
......@@ -114,7 +114,7 @@ namespace campvis {
createQuad();
// set this as painter to get notified when window size changes
setPainter(this, false);
setPainter(this);
getEventHandler()->addEventListenerToFront(this);
_geometryRenderer.init();
......
......@@ -239,17 +239,11 @@ namespace campvis {
}
void MainWindow::onPipelinesChanged() {
std::vector<AbstractPipeline*> pipelines;
std::for_each(_application->_pipelines.begin(), _application->_pipelines.end(), [&] (const CampVisApplication::PipelineRecord& pr) { pipelines.push_back(pr._pipeline); });
emit updatePipelineWidget(_application->_dataContainers, pipelines);
emit updatePipelineWidget(_application->_dataContainers, _application->_pipelines);
}
void MainWindow::onDataContainersChanged() {
std::vector<AbstractPipeline*> pipelines;
std::for_each(_application->_pipelines.begin(), _application->_pipelines.end(), [&] (const CampVisApplication::PipelineRecord& pr) { pipelines.push_back(pr._pipeline); });
emit updatePipelineWidget(_application->_dataContainers, pipelines);
emit updatePipelineWidget(_application->_dataContainers, _application->_pipelines);
}
void MainWindow::onPipelineWidgetItemChanged(const QModelIndex& index) {
......@@ -439,10 +433,7 @@ namespace campvis {
p->init();
_selectedPipeline->addProcessor(p);
std::vector<AbstractPipeline*> pipelines;
std::for_each(_application->_pipelines.begin(), _application->_pipelines.end(), [&] (const CampVisApplication::PipelineRecord& pr) { pipelines.push_back(pr._pipeline); });
emit updatePipelineWidget(_application->_dataContainers, pipelines);
emit updatePipelineWidget(_application->_dataContainers, _application->_pipelines);
}
void MainWindow::onRebuildShadersClicked() {
......
......@@ -232,7 +232,7 @@ namespace campvis {
GLCtxtMgr.registerContextAndInitGlew(_canvas, "Geometry1DTransferFunctionEditor");
GLCtxtMgr.releaseContext(_canvas, false);
_canvas->setPainter(this, false);
_canvas->setPainter(this);
_layout->addWidget(_canvas, 1, 1, 3, 3);
_lblIntensityLeft = new QLabel(QString::number(gtf->getIntensityDomain().x), this);
......
......@@ -219,7 +219,7 @@ namespace campvis {
GLCtxtMgr.registerContextAndInitGlew(_canvas, "Geometry2DTransferFunctionEditor");
GLCtxtMgr.releaseContext(_canvas, false);
_canvas->setPainter(this, false);
_canvas->setPainter(this);
_layout->addWidget(_canvas, 1, 1, 3, 3);
_lblIntensityLeft = new QLabel(QString::number(gtf->getIntensityDomain().x), this);
......
......@@ -52,6 +52,8 @@ namespace campvis {
{
cgtAssert(_data != 0, "Pointer to the DataContainer for this pipeline must not be 0!");
_painter.reset(new PipelinePainter(nullptr, this));
_enabled = false;
_pipelineDirty = true;
......@@ -60,12 +62,12 @@ namespace campvis {
}
AbstractPipeline::~AbstractPipeline() {
}
void AbstractPipeline::init() {
_data->s_dataAdded.connect(this, &AbstractPipeline::onDataContainerDataAdded);
_painter->init();
initAllProperties();
// initialize all processors:
......@@ -89,6 +91,7 @@ namespace campvis {
s_deinit.triggerSignal();
deinitAllProperties();
_painter->deinit();
// deinitialize all processors:
for (std::vector<AbstractProcessor*>::iterator it = _processors.begin(); it != _processors.end(); ++it) {
......@@ -240,7 +243,13 @@ namespace campvis {
}
void AbstractPipeline::setCanvas(cgt::GLCanvas* canvas) {
if (_canvas != nullptr)
_canvas->setPainter(nullptr);
_canvas = canvas;
if (_canvas != nullptr)
_canvas->setPainter(_painter.get());
}
void AbstractPipeline::setRenderTargetSize(const cgt::ivec2& size) {
......@@ -297,5 +306,10 @@ namespace campvis {
processor->setEnabled(enabledState);
}
const std::unique_ptr<PipelinePainter>& AbstractPipeline::getPipelinePainter() const {
return _painter;
}
}
......@@ -38,11 +38,13 @@
#include "core/coreapi.h"
#include "core/datastructures/datacontainer.h"
#include "core/pipeline/pipelinepainter.h"
#include "core/properties/datanameproperty.h"
#include "core/properties/floatingpointproperty.h"
#include "core/properties/propertycollection.h"
#include <map>
#include <memory>
#include <vector>
namespace cgt {
......@@ -126,6 +128,11 @@ namespace campvis {
* To be implemented in the subclass.
*/
virtual void executePipeline() = 0;
/**
* Sets the resultDirty flag of this pipeline and starts its execution if necessary.
*/
void setPipelineDirty();
/**
* Paints an additional overlay directly onto the frame buffer.
......@@ -208,17 +215,18 @@ namespace campvis {
*/
IVec2Property& getCanvasSize() {return _canvasSize;}
/**
* Returns this pipelines PipelinePainter.
* \return _painter
*/
const std::unique_ptr<PipelinePainter>& getPipelinePainter() const;
/// Signal emitted at the end of AbstractPipeline::init()
sigslot::signal0 s_init;
/// Signal emitted at the beginning of AbstractPipeline::deinit()
sigslot::signal0 s_deinit;
protected:
/**
* Sets the resultDirty flag of this pipeline and starts its execution if necessary.
*/
void setPipelineDirty();
/**
* Forces the execution of the given processor regardless of its invalidation or enabled state.
* \param processor Processor to execute.
......@@ -259,7 +267,8 @@ namespace campvis {
std::vector<AbstractProcessor*> _processors; ///< List of all processors of this pipeline
cgt::GLCanvas* _canvas; ///< Canvas hosting the OpenGL context for this pipeline.
cgt::GLCanvas* _canvas; ///< Canvas hosting the OpenGL context for this pipeline. We do *not* own this pointer.
std::unique_ptr<PipelinePainter> _painter; ///< PipelinePainter used to paint this pipeline's result onto the canvas.
IVec2Property _canvasSize; ///< original canvas size
bool _ignoreCanvasSizeUpdate;
......
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universitaet Muenchen
// Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
//
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// ================================================================================================
#include "campvispainter.h"
#include "cgt/assert.h"
#include "cgt/camera.h"
#include "cgt/glcontextmanager.h"
#include "cgt/shadermanager.h"
#include "cgt/texture.h"
#include "cgt/textureunit.h"
#include "cgt/qt/qtthreadedcanvas.h"
#include "core/datastructures/imagedata.h"
#include "core/datastructures/renderdata.h"
#include "core/datastructures/imagerepresentationgl.h"
#include "core/pipeline/abstractpipeline.h"
#include "core/tools/quadrenderer.h"
namespace campvis {
const std::string CampVisPainter::loggerCat_ = "CAMPVis.core.CampVisPainter";
CampVisPainter::CampVisPainter(cgt::GLCanvas* canvas, AbstractPipeline* pipeline)
: cgt::Painter(canvas)
, _pipeline(nullptr)
, _copyShader(nullptr)
, _errorTexture(nullptr)
{
cgtAssert(getCanvas() != nullptr, "The given canvas must not be 0!");
setPipeline(pipeline);
}
CampVisPainter::~CampVisPainter() {
}
void CampVisPainter::paint() {
if (getCanvas() == nullptr)
return;
if (_copyShader == nullptr) {
LERROR("Shader not initialized!");
return;
}
const cgt::ivec2& size = getCanvas()->getSize();
glViewport(0, 0, size.x, size.y);
// try get Data
DataHandle dh = _pipeline->getDataContainer().getData(_pipeline->getRenderTargetID());
const RenderData* rd = nullptr;
const ImageRepresentationGL* repGL = nullptr;
if (dh.getData() != nullptr) {
rd = dynamic_cast<const RenderData*>(dh.getData());
if (const ImageData* id = dynamic_cast<const ImageData*>(dh.getData()))
repGL = id->getRepresentation<ImageRepresentationGL>();
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// activate the shader
_copyShader->activate();
cgt::Shader::IgnoreUniformLocationErrorGuard guard(_copyShader);
// render whatever there is to render
if (rd != nullptr || (repGL != nullptr && repGL->getDimensionality() == 2)) {
_copyShader->setUniform("_viewMatrix", cgt::mat4::identity);
// bind input textures
cgt::TextureUnit colorUnit;
if (rd)
rd->bindColorTexture(_copyShader, colorUnit);
else if (repGL)
repGL->bind(_copyShader, colorUnit);
// execute the shader
QuadRdr.renderQuad();
}
// if there is nothing to render, render the error texture
else if (_errorTexture != nullptr) {
float ratioRatio = static_cast<float>(size.y) / size.x;
cgt::mat4 viewMatrix = (ratioRatio > 1) ? cgt::mat4::createScale(cgt::vec3(1.f, 1.f / ratioRatio, 1.f)) : cgt::mat4::createScale(cgt::vec3(ratioRatio, 1.f, 1.f));
_copyShader->setUniform("_viewMatrix", viewMatrix);
// bind input textures
cgt::TextureUnit colorUnit;
colorUnit.activate();
_errorTexture->bind();
_copyShader->setUniform("_colorTexture", colorUnit.getUnitNumber());
// execute the shader
QuadRdr.renderQuad();
}
else {
LERROR("Nothing to render but could not load error texture either.");
}
_copyShader->deactivate();
LGL_ERROR;
_pipeline->paint();
getCanvas()->swap();
}
void CampVisPainter::sizeChanged(const cgt::ivec2& size) {
_pipeline->setRenderTargetSize(size);
}
void CampVisPainter::init() {
try {
_copyShader = ShdrMgr.load("core/glsl/passthrough.vert", "core/glsl/copyimage.frag", "");
}
catch (cgt::Exception& e) {
LFATAL("Encountered cgt::Exception: " << e.what());
}
}
void CampVisPainter::deinit() {
ShdrMgr.dispose(_copyShader);
if (_pipeline != nullptr) {
if (getCanvas()->getEventHandler() != nullptr)
getCanvas()->getEventHandler()->removeEventListener(_pipeline);
_pipeline = nullptr;
}
}
void CampVisPainter::setPipeline(AbstractPipeline* pipeline) {
cgtAssert(pipeline != nullptr, "The given pipeline must not be 0.");
if (_pipeline != nullptr) {
if (getCanvas()->getEventHandler() != nullptr)
getCanvas()->getEventHandler()->removeEventListener(_pipeline);
}
_pipeline = pipeline;
_pipeline->setRenderTargetSize(getCanvas()->getSize());
if (getCanvas()->getEventHandler() != nullptr)
getCanvas()->getEventHandler()->addEventListenerToFront(_pipeline);
}
void CampVisPainter::repaint() {
// do nothing, as the painting is entirely managed by the pipeline.
}
void CampVisPainter::setCanvas(cgt::GLCanvas* canvas) {
cgtAssert(dynamic_cast<cgt::QtThreadedCanvas*>(canvas) != nullptr, "Canvas must be of type QtThreadedCanvas!");
Painter::setCanvas(canvas);
}
void CampVisPainter::setErrorTexture(cgt::Texture* texture) {
_errorTexture = texture;
}
}
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universitaet Muenchen
// Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
//
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// ================================================================================================
#include "pipelinepainter.h"
#include "cgt/assert.h"
#include "cgt/camera.h"
#include "cgt/glcontextmanager.h"
#include "cgt/logmanager.h"
#include "cgt/shadermanager.h"
#include "cgt/texture.h"
#include "cgt/textureunit.h"
#include "core/datastructures/imagedata.h"
#include "core/datastructures/renderdata.h"
#include "core/datastructures/imagerepresentationgl.h"
#include "core/pipeline/abstractpipeline.h"
#include "core/tools/quadrenderer.h"
namespace campvis {
const std::string PipelinePainter::loggerCat_ = "CAMPVis.core.PipelinePainter";
PipelinePainter::PipelinePainter(cgt::GLCanvas* canvas, AbstractPipeline* pipeline)
: cgt::Painter(canvas)
, _pipeline(pipeline)
, _copyShader(nullptr)
, _errorTexture(nullptr)
{
cgtAssert(pipeline != nullptr, "The given pipeline must not be 0!");
}
void PipelinePainter::paint() {
if (getCanvas() == nullptr)
return;
if (_copyShader == nullptr) {
LERROR("Shader not initialized!");
return;
}
const cgt::ivec2& size = getCanvas()->getSize();
glViewport(0, 0, size.x, size.y);
// try get Data
DataHandle dh = _pipeline->getDataContainer().getData(_pipeline->getRenderTargetID());
const RenderData* rd = nullptr;
const ImageRepresentationGL* repGL = nullptr;
if (dh.getData() != nullptr) {
rd = dynamic_cast<const RenderData*>(dh.getData());
if (const ImageData* id = dynamic_cast<const ImageData*>(dh.getData()))
repGL = id->getRepresentation<ImageRepresentationGL>();
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// activate the shader
_copyShader->activate();
cgt::Shader::IgnoreUniformLocationErrorGuard guard(_copyShader);
// render whatever there is to render
if (rd != nullptr || (repGL != nullptr && repGL->getDimensionality() == 2)) {
_copyShader->setUniform("_viewMatrix", cgt::mat4::identity);
// bind input textures
cgt::TextureUnit colorUnit;
if (rd)
rd->bindColorTexture(_copyShader, colorUnit);
else if (repGL)
repGL->bind(_copyShader, colorUnit);
// execute the shader
QuadRdr.renderQuad();
}
// if there is nothing to render, render the error texture
else if (_errorTexture != nullptr) {
float ratioRatio = static_cast<float>(size.y) / size.x;
cgt::mat4 viewMatrix = (ratioRatio > 1) ? cgt::mat4::createScale(cgt::vec3(1.f, 1.f / ratioRatio, 1.f)) : cgt::mat4::createScale(cgt::vec3(ratioRatio, 1.f, 1.f));
_copyShader->setUniform("_viewMatrix", viewMatrix);
// bind input textures
cgt::TextureUnit colorUnit;
colorUnit.activate();
_errorTexture->bind();
_copyShader->setUniform("_colorTexture", colorUnit.getUnitNumber());
// execute the shader
QuadRdr.renderQuad();
}
else {
LERROR("Nothing to render but could not load error texture either.");
}
_copyShader->deactivate();
LGL_ERROR;
_pipeline->paint();
getCanvas()->swap();
}
void PipelinePainter::sizeChanged(const cgt::ivec2& size) {
_pipeline->setRenderTargetSize(size);
}
void PipelinePainter::init() {
try {
_copyShader = ShdrMgr.load("core/glsl/passthrough.vert", "core/glsl/copyimage.frag", "");
}
catch (cgt::Exception& e) {
LFATAL("Encountered cgt::Exception: " << e.what());
}
}
void PipelinePainter::deinit() {
ShdrMgr.dispose(_copyShader);
if (getCanvas() != nullptr) {
if (getCanvas()->getEventHandler() != nullptr)
getCanvas()->getEventHandler()->removeEventListener(_pipeline);
_pipeline = nullptr;
}
}