Currently job artifacts in CI/CD pipelines on LRZ GitLab never expire. Starting from Wed 26.1.2022 the default expiration time will be 30 days (GitLab default). Currently existing artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

Commit 5ea6ef24 authored by schultezub's avatar schultezub
Browse files

various design revisions:

 * Moved paint() method out of VisualizationPipeline back to TumVisPainter
 * started using signals/slots instead of simple observer implementation

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@193 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent 29c1c9cb
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "tgt/qt/qtapplication.h" #include "tgt/qt/qtapplication.h"
#include "tgt/qt/qtcanvas.h" #include "tgt/qt/qtcanvas.h"
#include "tbb/include/tbb/task_scheduler_init.h"
#include "tumvispainter.h" #include "tumvispainter.h"
#include "modules/pipelines/slicevis.h" #include "modules/pipelines/slicevis.h"
...@@ -22,6 +24,7 @@ int main(int argc, char** argv) { ...@@ -22,6 +24,7 @@ int main(int argc, char** argv) {
tgt::QtCanvas* canvas = new tgt::QtCanvas("TUMVis"); tgt::QtCanvas* canvas = new tgt::QtCanvas("TUMVis");
SliceVis* sliceVis = 0; SliceVis* sliceVis = 0;
tbb::task_scheduler_init init;
app->addCanvas(canvas); app->addCanvas(canvas);
app->init(); app->init();
LogMgr.getConsoleLog()->addCat("", true); LogMgr.getConsoleLog()->addCat("", true);
...@@ -35,14 +38,14 @@ int main(int argc, char** argv) { ...@@ -35,14 +38,14 @@ int main(int argc, char** argv) {
} }
tgt::Camera camera; tgt::Camera camera;
canvas->setCamera(&camera); canvas->setCamera(&camera);
TumVisPainter* painter;
try { try {
sliceVis = new SliceVis(canvas); sliceVis = new SliceVis();
canvas->setPainter(sliceVis); painter = new TumVisPainter(canvas, sliceVis);
// TumVisPainter painter(canvas); canvas->setPainter(painter);
// canvas->setPainter(&painter); sliceVis->init();
} }
catch (tgt::Exception& e) { catch (tgt::Exception& e) {
LERRORC("main.cpp", "Encountered tgt::Exception: " << e.what()); LERRORC("main.cpp", "Encountered tgt::Exception: " << e.what());
...@@ -53,6 +56,7 @@ int main(int argc, char** argv) { ...@@ -53,6 +56,7 @@ int main(int argc, char** argv) {
app->run(); app->run();
delete painter;
delete sliceVis; delete sliceVis;
delete canvas; delete canvas;
delete app; delete app;
......
#include "tumvispainter.h" #include "tumvispainter.h"
#include "tgt/assert.h" #include "tgt/assert.h"
#include "tgt/camera.h" #include "tgt/camera.h"
#include "tgt/quadrenderer.h"
#include "tgt/quadric.h" #include "tgt/quadric.h"
#include "core/datastructures/imagedatarendertarget.h"
namespace TUMVis { namespace TUMVis {
const std::string TumVisPainter::loggerCat_ = "TUMVis.core.TumVisPainter"; const std::string TumVisPainter::loggerCat_ = "TUMVis.core.TumVisPainter";
TumVisPainter::TumVisPainter(tgt::GLCanvas* canvas) TumVisPainter::TumVisPainter(tgt::GLCanvas* canvas, VisualizationPipeline* pipeline)
: tgt::Painter(canvas) : tgt::Painter(canvas)
, _pipeline(0)
, _dirty(0)
, _currentlyRendering(false)
, _copyShader(0)
{ {
tgtAssert(getCanvas() != 0, "The given canvas must not be 0!"); tgtAssert(getCanvas() != 0, "The given canvas must not be 0!");
setPipeline(pipeline);
} }
void TumVisPainter::paint() { void TumVisPainter::paint() {
// Put TUMVis rendering pipeline evaluation inside if (getCanvas() == 0)
return;
// Some Dummy rendering: {
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); tbb::mutex::scoped_lock lock(_localMutex);
getCamera()->look(); _currentlyRendering = true;
glColor3f(1.f, 0.f, 0.f); _dirty = false;
tgt::Sphere sphere(.5f, 64, 32); }
sphere.render();
// get OpenGL focus and setup context
getCanvas()->getGLFocus();
const tgt::ivec2 size = getCanvas()->getSize();
glViewport(0, 0, size.x, size.y);
// try get Data
const ImageDataRenderTarget* image = _pipeline->getRenderTarget();
if (image != 0) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// activate shader
_copyShader->activate();
_copyShader->setIgnoreUniformLocationError(true);
_copyShader->setUniform("_viewportSize", size);
_copyShader->setUniform("_viewportSizeRCP", 1.f / tgt::vec2(size));
_copyShader->setIgnoreUniformLocationError(false);
// bind input textures
tgt::TextureUnit colorUnit, depthUnit;
image->bind(_copyShader, colorUnit, depthUnit);
LGL_ERROR;
// execute the shader
tgt::QuadRenderer::renderQuad();
_copyShader->deactivate();
LGL_ERROR;
}
else {
// TODO: render some nifty error texture
// so long, we do some dummy rendering
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
getCamera()->setPosition(tgt::vec3(0.f,0.f,2.f));
getCamera()->look();
glColor3f(1.f, 0.f, 0.f);
tgt::Sphere sphere(.5f, 64, 32);
sphere.render();
/*
// render error texture
if (!errorTex_) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
return;
}
glClear(GL_DEPTH_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
errorTex_->bind();
errorTex_->enable();
glColor3f(1.f, 1.f, 1.f);
renderQuad();
errorTex_->disable();*/
}
LGL_ERROR;
{
tbb::mutex::scoped_lock lock(_localMutex);
_currentlyRendering = false;
}
if (_dirty)
getCanvas()->repaint();
} }
void TumVisPainter::sizeChanged(const tgt::ivec2& size) { void TumVisPainter::sizeChanged(const tgt::ivec2& size) {
if (getCanvas()) { if (getCanvas()) {
getCanvas()->getGLFocus(); getCanvas()->getGLFocus();
} }
glViewport(0, 0, size.x, size.y); _pipeline->setRenderTargetSize(size);
getCamera()->setRatio((float) size.x/size.y);
} }
void TumVisPainter::init() { void TumVisPainter::init() {
if (getCanvas()) { try {
getCanvas()->getGLFocus(); // TODO: Remove hardcoded paths, and use ShdrMgr.addPath() at some central location
_copyShader = ShdrMgr.loadSeparate("core/glsl/passthrough.vert", "core/glsl/copyimage.frag", "", false);
} }
else { catch (tgt::Exception& e) {
LWARNING("initialize(): No canvas"); LERRORC("main.cpp", "Encountered tgt::Exception: " << e.what());
} }
}
glEnable(GL_DEPTH_TEST); void TumVisPainter::setPipeline(VisualizationPipeline* pipeline) {
glShadeModel(GL_SMOOTH); tgtAssert(pipeline != 0, "The given pipeline must not be 0.");
glEnable(GL_COLOR_MATERIAL); if (_pipeline != 0) {
glEnable(GL_LIGHTING); _pipeline->s_renderTargetChanged.disconnect(this);
glEnable(GL_LIGHT0); if (getCanvas()->getEventHandler() != 0)
getCanvas()->getEventHandler()->removeListener(_pipeline);
getCamera()->setPosition(tgt::vec3(0.f,0.f,2.f)); }
/*
_pipeline = pipeline;
_pipeline->s_renderTargetChanged.connect(this, &TumVisPainter::onPipelineInvalidated);
_pipeline->setRenderTargetSize(getCanvas()->getSize());
if (getCanvas()->getEventHandler() != 0)
getCanvas()->getEventHandler()->addListenerToFront(_pipeline);
}
glEnable(GL_DEPTH_TEST); void TumVisPainter::onPipelineInvalidated() {
glDepthFunc(GL_LESS); if (! _currentlyRendering)
glDisable(GL_CULL_FACE); getCanvas()->repaint();
glCullFace(GL_BACK);*/ else {
tbb::mutex::scoped_lock lock(_localMutex);
_dirty = true;
}
} }
} }
\ No newline at end of file
#include "sigslot/sigslot.h"
#include "tbb/include/tbb/mutex.h"
#include "tgt/logmanager.h" #include "tgt/logmanager.h"
#include "tgt/glcanvas.h" #include "tgt/glcanvas.h"
#include "tgt/painter.h" #include "tgt/painter.h"
#include "tgt/event/eventhandler.h" #include "tgt/event/eventhandler.h"
#include "core/pipeline/visualizationpipeline.h"
namespace tgt {
class Shader;
}
namespace TUMVis { namespace TUMVis {
/** /**
...@@ -10,18 +18,26 @@ namespace TUMVis { ...@@ -10,18 +18,26 @@ namespace TUMVis {
* *
* \todo * \todo
*/ */
class TumVisPainter : public tgt::Painter { class TumVisPainter : public tgt::Painter, public sigslot::has_slots<> {
public: public:
TumVisPainter(tgt::GLCanvas* canvas); TumVisPainter(tgt::GLCanvas* canvas, VisualizationPipeline* pipeline);
virtual void paint(); virtual void paint();
virtual void sizeChanged(const tgt::ivec2& size); virtual void sizeChanged(const tgt::ivec2& size);
virtual void init(); virtual void init();
void setPipeline(VisualizationPipeline* pipeline);
void onPipelineInvalidated();
private: private:
static const std::string loggerCat_; static const std::string loggerCat_;
float _size; VisualizationPipeline* _pipeline;
bool _dirty;
bool _currentlyRendering;
tgt::Shader* _copyShader; ///< Shader for copying the render target to the framebuffer.
tbb::mutex _localMutex;
}; };
} }
...@@ -16,22 +16,25 @@ namespace TUMVis { ...@@ -16,22 +16,25 @@ namespace TUMVis {
} }
const DataHandle* DataContainer::addData(const std::string& name, AbstractData* data) { const DataHandle* DataContainer::addData(const std::string& name, AbstractData* data) {
DataHandle* dh = new DataHandle(this, data); DataHandle* dh = new DataHandle(data);
addDataHandle(name, dh); addDataHandle(name, dh);
return dh; return dh;
} }
void DataContainer::addDataHandle(const std::string& name, const DataHandle* dh) { void DataContainer::addDataHandle(const std::string& name, const DataHandle* dh) {
tbb::spin_mutex::scoped_lock lock(_localMutex); {
std::map<std::string, const DataHandle*>::iterator it = _handles.lower_bound(name); tbb::spin_mutex::scoped_lock lock(_localMutex);
if (it != _handles.end() && it->first == name) { std::map<std::string, const DataHandle*>::iterator it = _handles.lower_bound(name);
DataHandle::removeOwner(it->second, this); if (it != _handles.end() && it->first == name) {
it->second = dh; DataHandle::removeOwner(it->second, this);
} it->second = dh;
else { }
_handles.insert(it, std::make_pair(name, dh)); else {
_handles.insert(it, std::make_pair(name, dh));
}
} }
DataHandle::addOwner(dh, this); DataHandle::addOwner(dh, this);
s_dataAdded(name, dh);
} }
bool DataContainer::hasData(const std::string& name) const { bool DataContainer::hasData(const std::string& name) const {
......
#ifndef DATACONTAINER_H__ #ifndef DATACONTAINER_H__
#define DATACONTAINER_H__ #define DATACONTAINER_H__
#include "sigslot/sigslot.h"
#include "tbb/include/tbb/spin_mutex.h" #include "tbb/include/tbb/spin_mutex.h"
#include "core/datastructures/abstractdata.h" #include "core/datastructures/abstractdata.h"
#include "core/datastructures/datahandle.h" #include "core/datastructures/datahandle.h"
#include "core/tools/observer.h"
#include <string> #include <string>
#include <map> #include <map>
namespace TUMVis { namespace TUMVis {
/** /**
* A DataContainer manages instances of AbstractData and offers access to them via string identifiers (names/keys). * A DataContainer manages instances of AbstractData and offers access to them via string identifiers (names/keys).
* Therefore, it stores them in DataHandles which take ownership of the AbstractData instance. Hence, * Therefore, it stores them in DataHandles which take ownership of the AbstractData instance. Hence,
...@@ -41,7 +42,7 @@ namespace TUMVis { ...@@ -41,7 +42,7 @@ namespace TUMVis {
/** /**
* Adds the given AbstractData instance \a data, accessible by the key \name, to this DataContainer. * Adds the given AbstractData instance \a data, accessible by the key \name, to this DataContainer.
* In doing so, the DataContainer (respectively the created DataHandle) takes ownership of \a data * In doing so, the DataContainer (respectively the created DataHandle) takes ownership of \a data
* and will manage its lifetime. So don't even dare to delete \a data yourself! * and will manage its lifetime. So don't even think about deleting \a data yourself!
* *
* \param name Key for accessing the DataHandle within this DataContainer * \param name Key for accessing the DataHandle within this DataContainer
* \param data DataHandle to add. * \param data DataHandle to add.
...@@ -86,6 +87,9 @@ namespace TUMVis { ...@@ -86,6 +87,9 @@ namespace TUMVis {
template<typename T> template<typename T>
inline const T* getTypedData(const std::string& name) const; inline const T* getTypedData(const std::string& name) const;
sigslot::signal2<const std::string&, const DataHandle*> s_dataAdded;
private: private:
std::map<std::string, const DataHandle*> _handles; std::map<std::string, const DataHandle*> _handles;
mutable tbb::spin_mutex _localMutex; mutable tbb::spin_mutex _localMutex;
......
...@@ -6,10 +6,11 @@ namespace TUMVis { ...@@ -6,10 +6,11 @@ namespace TUMVis {
const std::string DataHandle::loggerCat_ = "TUMVis.core.datastructures.DataHandle"; const std::string DataHandle::loggerCat_ = "TUMVis.core.datastructures.DataHandle";
DataHandle::DataHandle(const DataContainer* owner, AbstractData* data) DataHandle::DataHandle(AbstractData* data, const DataContainer* owner /*= 0*/)
: _data(data) : _data(data)
{ {
addOwner(this, owner); if (owner != 0)
addOwner(this, owner);
} }
DataHandle::~DataHandle() { DataHandle::~DataHandle() {
......
...@@ -53,13 +53,13 @@ namespace TUMVis { ...@@ -53,13 +53,13 @@ namespace TUMVis {
private: private:
/** /**
* Creates a new DataHandle for \a data and takes its ownership in terms of lifetime management. * Creates a new DataHandle for \a data and takes its ownership in terms of lifetime management.
* The DataContainer \a owner will automatically be added to the set of owners of this DataHandle, so * If \a owner != 0, it will automatically be added to the set of owners of this DataHandle, so
* it is NOT needed to call DataHandle::addOwner(). * in this case it is NOT needed to call DataHandle::addOwner().
* *
* \param owner Initial owner of this DataHandle (usually the DataContainer creating the handle)
* \param data AbstractData instance to manage * \param data AbstractData instance to manage
* \param owner Initial owner of this DataHandle, may be 0.
*/ */
DataHandle(const DataContainer* owner, AbstractData* data); DataHandle(AbstractData* data, const DataContainer* owner = 0);
/** /**
* DO NOT USE - it is private on purpose! * DO NOT USE - it is private on purpose!
......
#include "mwheeltonumericpropertyeventhandler.h" #include "mwheeltonumericpropertyeventhandler.h"
#include "tgt/assert.h" #include "tgt/assert.h"
#include "tgt/event/mouseevent.h" #include "tgt/event/mouseevent.h"
namespace TUMVis { namespace TUMVis {
const std::string MWheelToNumericPropertyEventHandler::loggerCat_ = "TUMVis.core.eventhandler.MWheelToNumericPropertyEventHandler"; const std::string MWheelToNumericPropertyEventHandler::loggerCat_ = "TUMVis.core.eventhandler.MWheelToNumericPropertyEventHandler";
......
...@@ -27,4 +27,15 @@ namespace TUMVis { ...@@ -27,4 +27,15 @@ namespace TUMVis {
} }
} }
void AbstractPipeline::onNotify(const ProcessorObserverArgs& poa) {
// tbb::spin_mutex::scoped_lock lock(_localMutex);
// _invalidationLevel.setLevel(InvalidationLevel::INVALID_RESULT);
execute();
}
const DataContainer& AbstractPipeline::getDataContainer() const {
return _data;
}
} }
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
#define ABSTRACTPIPELINE_H__ #define ABSTRACTPIPELINE_H__
#include "tgt/logmanager.h" #include "tgt/logmanager.h"
#include "tbb/include/tbb/spin_mutex.h"
#include "core/tools/observer.h"
#include "core/tools/invalidationlevel.h"
#include "core/datastructures/datacontainer.h" #include "core/datastructures/datacontainer.h"
#include "core/pipeline/abstractprocessor.h" #include "core/pipeline/abstractprocessor.h"
#include "core/properties/propertycollection.h" #include "core/properties/propertycollection.h"
...@@ -14,7 +17,7 @@ namespace TUMVis { ...@@ -14,7 +17,7 @@ namespace TUMVis {
* Abstract base class for TUMVis Pipelines. * Abstract base class for TUMVis Pipelines.
* *
*/ */
class AbstractPipeline { class AbstractPipeline : public GenericObserver<ProcessorObserverArgs> {
public: public:
/** /**
* Creates a AbstractPipeline. * Creates a AbstractPipeline.
...@@ -40,16 +43,33 @@ namespace TUMVis { ...@@ -40,16 +43,33 @@ namespace TUMVis {
virtual void execute() = 0; virtual void execute() = 0;
/** /**
* Returns the PropertyCollection of this processor. * Returns the PropertyCollection of this pipeline.
* \return _properties * \return _properties
*/ */
PropertyCollection& getPropertyCollection(); PropertyCollection& getPropertyCollection();
/**
* Returns the DataContainer of this pipeline
* \return _data
*/
const DataContainer& getDataContainer() const;
/**
* Gets called when one of the observed processors changed and thus notifies its observers.
* The default behaviour is just to set the invalidation level to invalid.
* \sa GenericObserver::onNotify, AbstractProcessor
* \param poa ProcessorObserverArgs ObserverArgument struct containing the emitting processor and its InvalidationLevel
*/
virtual void onNotify(const ProcessorObserverArgs& poa);
protected: protected:
DataContainer _data; ///< DataContainer containing local working set of data for this Pipeline DataContainer _data; ///< DataContainer containing local working set of data for this Pipeline
std::vector<AbstractProcessor*> _processors; ///< List of all processors of this pipeline std::vector<AbstractProcessor*> _processors; ///< List of all processors of this pipeline
PropertyCollection _properties; ///< PropertyCollection of this pipeline, put in here all properties you want to be publicly accessible PropertyCollection _properties; ///< PropertyCollection of this pipeline, put in here all properties you want to be publicly accessible
InvalidationLevel _invalidationLevel; ///< current invalidation level
tbb::spin_mutex _localMutex; ///< mutex for altering local members
static const std::string loggerCat_; static const std::string loggerCat_;
}; };
......
...@@ -7,21 +7,22 @@ ...@@ -7,21 +7,22 @@
namespace TUMVis { namespace TUMVis {
const std::string VisualizationPipeline::loggerCat_ = "TUMVis.core.datastructures.VisualizationPipeline"; const std::string VisualizationPipeline::loggerCat_ = "TUMVis.core.datastructures.VisualizationPipeline";
VisualizationPipeline::VisualizationPipeline(tgt::GLCanvas* canvas /*= 0*/) VisualizationPipeline::VisualizationPipeline()
: AbstractPipeline() : AbstractPipeline()
, _canvas(0) , tgt::EventListener()
, _canvasSize("canvasSize", "Canvas Size", tgt::ivec2(128, 128)) , _renderTargetSize("canvasSize", "Canvas Size", tgt::ivec2(128, 128))
, _renderTargetID("renderTargetID", "Render Target ID", "VisualizationPipeline.renderTarget") , _renderTargetID("renderTargetID", "Render Target ID", "VisualizationPipeline.renderTarget")
{ {
setCanvas(canvas); _data.s_dataAdded.connect(this, &VisualizationPipeline::onDataContainerDataAdded);
} }
VisualizationPipeline::~VisualizationPipeline() { VisualizationPipeline::~VisualizationPipeline() {
_data.s_dataAdded.disconnect(this);
} }
void VisualizationPipeline::onEvent(tgt::Event* e) { void VisualizationPipeline::onEvent(tgt::Event* e) {
// cycle through event handlers, ask each one if it handles the event and if so, execute it. // cycle through event handlers, ask each one if it handles the event and if so, execute