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

Moved invalidation level from AbstractProperty to AbstractProcessor:

To now, each property hat an _invalidationLevel field that was evaluated by processors when the property had changed in order to determine what has to be done. However, since properties could also be owned by other classes, this design was semantically misleading.
Therefore, it was removed with this commit and replaced by the invalidation map of each processor. Now, this per-processor mapping of property -> invalidation level is managed by the processor itself. Furthermore, the invalidation level is no longer setup during property creation but during AbstractProcessor::addProperty(), which also makes much more sense.

ATTENTION: Due to these intrusive API changes, the code of all processors and other classes handling properties needs to be changed. As a reminder, the implementation of addProperty() also now takes a reference instead of a pointer, so that old code does no longer compile.

refs #542
parent 94a730da
......@@ -77,13 +77,13 @@ namespace campvis {
exit(EXIT_FAILURE);
}
addProperty(&p_currentSlice);
addProperty(&p_transferFunction);
addProperty(&p_meshSolidColor);
addProperty(&p_renderRChannel);
addProperty(&p_renderGChannel);
addProperty(&p_renderBChannel);
addProperty(&p_renderAChannel);
addProperty(p_currentSlice);
addProperty(p_transferFunction);
addProperty(p_meshSolidColor);
addProperty(p_renderRChannel);
addProperty(p_renderGChannel);
addProperty(p_renderBChannel);
addProperty(p_renderAChannel);
}
DataContainerInspectorCanvas::~DataContainerInspectorCanvas() {
......
......@@ -36,7 +36,7 @@ namespace campvis {
SimpleTransferFunction::SimpleTransferFunction(size_t size, const tgt::vec2& intensityDomain /*= tgt::vec2(0.f, 1.f)*/)
: AbstractTransferFunction(tgt::svec3(size, 1, 1), intensityDomain)
, _leftColor(0, 0, 0, 0)
, _leftColor(0, 0, 0, 255)
, _rightColor(255)
{
}
......
......@@ -76,8 +76,8 @@ namespace campvis {
_enabled = false;
addProperty(&_renderTargetID);
addProperty(&_canvasSize);
addProperty(_renderTargetID);
addProperty(_canvasSize);
}
AbstractPipeline::~AbstractPipeline() {
......
......@@ -84,7 +84,12 @@ namespace campvis {
}
void AbstractProcessor::onPropertyChanged(const AbstractProperty* prop) {
invalidate(prop->getInvalidationLevel());
tbb::spin_rw_mutex::scoped_lock lock(_mtxInvalidationMap, false);
auto it = _invalidationMap.find(prop);
if (it != _invalidationMap.end())
invalidate(it->second);
else
LDEBUG("Caught an property changed signal that was not registered with an invalidation level. Did you forget to call addProperty()?");
}
bool AbstractProcessor::getEnabled() const {
......@@ -149,6 +154,20 @@ namespace campvis {
validate(INVALID_PROPERTIES);
}
void AbstractProcessor::addProperty(AbstractProperty& prop) {
this->addProperty(prop, INVALID_RESULT);
}
void AbstractProcessor::addProperty(AbstractProperty& prop, int invalidationLevel) {
HasPropertyCollection::addProperty(prop);
setPropertyInvalidationLevel(prop, invalidationLevel);
}
void AbstractProcessor::setPropertyInvalidationLevel(AbstractProperty& prop, int invalidationLevel) {
tbb::spin_rw_mutex::scoped_lock lock(_mtxInvalidationMap, true);
_invalidationMap[&prop] = invalidationLevel;
}
// ================================================================================================
AbstractProcessor::ScopedLock::ScopedLock(AbstractProcessor* p, bool unlockInExtraThread)
......
......@@ -25,15 +25,18 @@
#ifndef PROCESSOR_H__
#define PROCESSOR_H__
#include "sigslot/sigslot.h"
#include <tbb/atomic.h>
#include <tbb/concurrent_queue.h>
#include <tbb/spin_rw_mutex.h>
#include "sigslot/sigslot.h"
#include "tgt/logmanager.h"
#include "core/coreapi.h"
#include "core/datastructures/datacontainer.h"
#include "core/properties/propertycollection.h"
#include <unordered_map>
#include <string>
#include <vector>
......@@ -122,6 +125,31 @@ namespace campvis {
*/
virtual ProcessorState getProcessorState() const = 0;
/**
* Registers \a prop as property with the default invalidation level of INVALID_RESULT.
* \see HasPropertyCollection::addProperty()
* \param prop Property to register
*/
virtual void addProperty(AbstractProperty& prop);
/**
* Registers \a prop as property with the provided invalidation level. Registered properties
* can be accessed from the outside, e.g. via getProperty(), and will automatically invalidate
* this processor on change. An already existing property with the same name will be replaced.
*
* \param prop Property to add
* \param invalidationLevel Invalidation level of this property
*/
void addProperty(AbstractProperty& prop, int invalidationLevel);
/**
* Sets the property invalidation level to the specified value.
*
* \param prop Property whose invalidation level is to change.
* \param invalidationLevel New invalidation level of this property
*/
void setPropertyInvalidationLevel(AbstractProperty& prop, int invalidationLevel);
/**
* Execute this processor.
* Locks the processor and calls updateShader(), updateProperties() and/or updateResult()
......@@ -325,6 +353,10 @@ namespace campvis {
/// (This implies, that all properties are locked and it is not valid to call process())
tbb::atomic<bool> _locked;
tbb::spin_rw_mutex _mtxInvalidationMap; ///< Mutex protecting _invalidationMap
/// Hash map storing the invalidation levels for each registered property
std::unordered_map<const AbstractProperty*, int> _invalidationMap;
private:
tbb::atomic<int> _level; ///< current invalidation level
tbb::concurrent_queue<int> _queuedInvalidations;
......
......@@ -29,7 +29,7 @@
namespace campvis {
void AbstractProcessorDecorator::addProperties(HasPropertyCollection* propCollection) {
void AbstractProcessorDecorator::addProperties(AbstractProcessor* propCollection) {
}
void AbstractProcessorDecorator::renderProlog(const DataContainer& dataContainer, tgt::Shader* shader) {
......@@ -57,7 +57,7 @@ namespace campvis {
_decorators.push_back(decorator);
}
void HasProcessorDecorators::decoratePropertyCollection(HasPropertyCollection* propCollection) const {
void HasProcessorDecorators::decoratePropertyCollection(AbstractProcessor* propCollection) const {
for (std::vector<AbstractProcessorDecorator*>::const_iterator it = _decorators.begin(); it != _decorators.end(); ++it)
(*it)->addProperties(propCollection);
}
......
......@@ -36,7 +36,7 @@ namespace tgt {
namespace campvis {
class DataContainer;
class HasPropertyCollection;
class AbstractProcessor;
/**
* Abstract base class for processor decorators.
......@@ -55,7 +55,7 @@ namespace campvis {
* add its properties to the processor.
* \param propCollection PropertyCollection defining where to add the properties (usually the owning processor).
*/
virtual void addProperties(HasPropertyCollection* propCollection);
virtual void addProperties(AbstractProcessor* propCollection);
/**
* Gets called by the processor with an active OpenGL context having \a shader activated before the
......@@ -106,7 +106,7 @@ namespace campvis {
* Decorates \a propCollection with the properties of all held decorators.
* \param propCollection PropertyCollection to decorate (usually your processor)
*/
void decoratePropertyCollection(HasPropertyCollection* propCollection) const;
void decoratePropertyCollection(AbstractProcessor* propCollection) const;
/**
* Calls renderProlog() on each held decorator.
......
......@@ -41,8 +41,8 @@ namespace campvis {
}
void ProcessorDecoratorBackground::addProperties(HasPropertyCollection* propCollection) {
propCollection->addProperty(&_backgroundColor1);
propCollection->addProperty(&_backgroundColor2);
propCollection->addProperty(_backgroundColor1);
propCollection->addProperty(_backgroundColor2);
}
void ProcessorDecoratorBackground::renderProlog(const DataContainer& dataContainer, tgt::Shader* shader) {
......
......@@ -25,7 +25,7 @@
#include "processordecoratorgradient.h"
#include "tgt/shadermanager.h"
#include "core/properties/propertycollection.h"
#include "core/pipeline/abstractprocessor.h"
namespace campvis {
static const GenericOption<ProcessorDecoratorGradient::GradientMethod> gradientOptions[4] = {
......@@ -37,7 +37,7 @@ namespace campvis {
ProcessorDecoratorGradient::ProcessorDecoratorGradient()
: AbstractProcessorDecorator()
, p_gradientMethod("GradientMethod", "Gradient Computation Method", gradientOptions, 4, AbstractProcessor::INVALID_SHADER | AbstractProcessor::INVALID_RESULT)
, p_gradientMethod("GradientMethod", "Gradient Computation Method", gradientOptions, 4)
, p_lod("GradientLod", "LOD for Gradient Computation", 0.5f, 0.f, 5.f, .1f, 1)
{
p_gradientMethod.setValue(1);
......@@ -48,9 +48,9 @@ namespace campvis {
p_gradientMethod.s_changed.disconnect(this);
}
void ProcessorDecoratorGradient::addProperties(HasPropertyCollection* propCollection) {
propCollection->addProperty(&p_gradientMethod);
propCollection->addProperty(&p_lod);
void ProcessorDecoratorGradient::addProperties(AbstractProcessor* propCollection) {
propCollection->addProperty(p_gradientMethod, AbstractProcessor::INVALID_SHADER | AbstractProcessor::INVALID_RESULT);
propCollection->addProperty(p_lod);
}
std::string ProcessorDecoratorGradient::generateHeader() const {
......
......@@ -58,7 +58,7 @@ namespace campvis {
protected:
/// \see AbstractProcessorDecorator::addProperties()
void addProperties(HasPropertyCollection* propCollection);
void addProperties(AbstractProcessor* propCollection);
/// \see AbstractProcessorDecorator::renderProlog()
virtual void renderProlog(const DataContainer& dataContainer, tgt::Shader* shader);
/// \see AbstractProcessorDecorator::generateHeader()
......
......@@ -25,13 +25,13 @@
#include "processordecoratormasking.h"
#include "tgt/shadermanager.h"
#include "core/properties/propertycollection.h"
#include "core/pipeline/abstractprocessor.h"
namespace campvis {
ProcessorDecoratorMasking::ProcessorDecoratorMasking()
: AbstractProcessorDecorator()
, _applyMask("applyMask", "Apply Mask to image", false, AbstractProcessor::INVALID_SHADER)
, _applyMask("applyMask", "Apply Mask to image", false)
, _maskID("maskID", "Mask Image ID", "mask", DataNameProperty::READ)
, _maskColor("maskColor", "Mask Color", tgt::vec4(0.f), tgt::vec4(0.f), tgt::vec4(1.f))
, _texUnit(0)
......@@ -48,10 +48,10 @@ namespace campvis {
delete _maskImage;
}
void ProcessorDecoratorMasking::addProperties(HasPropertyCollection* propCollection) {
propCollection->addProperty(&_applyMask);
propCollection->addProperty(&_maskID);
propCollection->addProperty(&_maskColor);
void ProcessorDecoratorMasking::addProperties(AbstractProcessor* propCollection) {
propCollection->addProperty(_applyMask, AbstractProcessor::INVALID_SHADER);
propCollection->addProperty(_maskID);
propCollection->addProperty(_maskColor);
}
void ProcessorDecoratorMasking::renderProlog(const DataContainer& dataContainer, tgt::Shader* shader) {
......
......@@ -41,7 +41,7 @@ namespace campvis {
virtual ~ProcessorDecoratorMasking();
protected:
void addProperties(HasPropertyCollection* propCollection);
void addProperties(AbstractProcessor* propCollection);
void renderProlog(const DataContainer& dataContainer, tgt::Shader* shader);
......
......@@ -25,12 +25,12 @@
#include "processordecoratorshading.h"
#include "tgt/shadermanager.h"
#include "core/properties/propertycollection.h"
#include "core/pipeline/abstractprocessor.h"
namespace campvis {
ProcessorDecoratorShading::ProcessorDecoratorShading(const std::string& lightUniformName /*= "_lightSource"*/)
: ProcessorDecoratorGradient()
, _enableShading("EnableShading", "Enable Shading", true, AbstractProcessor::INVALID_SHADER | AbstractProcessor::INVALID_RESULT)
, _enableShading("EnableShading", "Enable Shading", true)
, _lightPosition("LightPosition", "Light Position", tgt::vec3(-100.f), tgt::vec3(-500.f), tgt::vec3(500.f), tgt::vec3(1.f))
, _ambientColor("AmbientColor", "Ambient Light Color", tgt::vec3(0.4f), tgt::vec3(0.f), tgt::vec3(1.f))
, _diffuseColor("DiffuseColor", "Diffuse Light Color", tgt::vec3(0.75f), tgt::vec3(0.f), tgt::vec3(1.f))
......@@ -44,16 +44,16 @@ namespace campvis {
ProcessorDecoratorShading::~ProcessorDecoratorShading() {
}
void ProcessorDecoratorShading::addProperties(HasPropertyCollection* propCollection) {
propCollection->addProperty(&_enableShading);
void ProcessorDecoratorShading::addProperties(AbstractProcessor* propCollection) {
propCollection->addProperty(_enableShading, AbstractProcessor::INVALID_SHADER | AbstractProcessor::INVALID_RESULT);
ProcessorDecoratorGradient::addProperties(propCollection);
propCollection->addProperty(&_lightPosition);
propCollection->addProperty(&_ambientColor);
propCollection->addProperty(&_diffuseColor);
propCollection->addProperty(&_specularColor);
propCollection->addProperty(&_shininess);
propCollection->addProperty(&_attenuation);
propCollection->addProperty(_lightPosition);
propCollection->addProperty(_ambientColor);
propCollection->addProperty(_diffuseColor);
propCollection->addProperty(_specularColor);
propCollection->addProperty(_shininess);
propCollection->addProperty(_attenuation);
}
void ProcessorDecoratorShading::renderProlog(const DataContainer& dataContainer, tgt::Shader* shader) {
......
......@@ -40,7 +40,7 @@ namespace campvis {
virtual ~ProcessorDecoratorShading();
protected:
void addProperties(HasPropertyCollection* propCollection);
void addProperties(AbstractProcessor* propCollection);
void renderProlog(const DataContainer& dataContainer, tgt::Shader* shader);
......
......@@ -39,7 +39,7 @@ namespace campvis {
RaycastingProcessor::RaycastingProcessor(IVec2Property* viewportSizeProp, const std::string& fragmentShaderFileName, bool bindEntryExitDepthTextures, const std::string& customGlslVersion /*= ""*/)
: VisualizationProcessor(viewportSizeProp)
, p_sourceImageID("sourceImageID", "Input Image", "", DataNameProperty::READ, AbstractProcessor::INVALID_RESULT | AbstractProcessor::INVALID_PROPERTIES)
, p_sourceImageID("sourceImageID", "Input Image", "", DataNameProperty::READ)
, p_entryImageID("entryImageID", "Input Entry Points Image", "", DataNameProperty::READ)
, p_exitImageID("exitImageID", "Input Exit Points Image", "", DataNameProperty::READ)
, p_targetImageID("targetImageID", "Output Image", "", DataNameProperty::WRITE)
......@@ -52,14 +52,14 @@ namespace campvis {
, _shader(0)
, _bindEntryExitDepthTextures(bindEntryExitDepthTextures)
{
addProperty(&p_sourceImageID);
addProperty(&p_entryImageID);
addProperty(&p_exitImageID);
addProperty(&p_targetImageID);
addProperty(&p_camera);
addProperty(&p_transferFunction);
addProperty(&p_jitterStepSizeMultiplier);
addProperty(&p_samplingRate);
addProperty(p_sourceImageID, AbstractProcessor::INVALID_RESULT | AbstractProcessor::INVALID_PROPERTIES);
addProperty(p_entryImageID);
addProperty(p_exitImageID);
addProperty(p_targetImageID);
addProperty(p_camera);
addProperty(p_transferFunction);
addProperty(p_jitterStepSizeMultiplier);
addProperty(p_samplingRate);
}
RaycastingProcessor::~RaycastingProcessor() {
......
......@@ -48,10 +48,11 @@ namespace campvis {
AbstractProcessor::init();
tgtAssert(_viewportSizeProperty != 0, "The pointer to the viewport size property must not be 0!");
addProperty(&p_lqMode);
addProperty(p_lqMode);
_fbo = new tgt::FramebufferObject();
_viewportSizeProperty->s_changed.connect<VisualizationProcessor>(this, &VisualizationProcessor::onPropertyChanged);
setPropertyInvalidationLevel(*_viewportSizeProperty, INVALID_RESULT);
}
void VisualizationProcessor::deinit() {
......@@ -169,10 +170,13 @@ namespace campvis {
void VisualizationProcessor::setViewportSizeProperty(IVec2Property* viewportSizeProp) {
tgtAssert(viewportSizeProp != 0, "Pointer must not be 0.");
if (_viewportSizeProperty != 0)
if (_viewportSizeProperty != 0) {
_viewportSizeProperty->s_changed.disconnect(this);
}
_viewportSizeProperty = viewportSizeProp;
_viewportSizeProperty->s_changed.connect<VisualizationProcessor>(this, &VisualizationProcessor::onPropertyChanged);
setPropertyInvalidationLevel(*viewportSizeProp, INVALID_RESULT);
}
}
......@@ -28,10 +28,9 @@ namespace campvis {
const std::string AbstractProperty::loggerCat_ = "CAMPVis.core.datastructures.AbstractProperty";
AbstractProperty::AbstractProperty(const std::string& name, const std::string& title, int invalidationLevel /*= AbstractProcessor::INVALID_RESULT*/)
AbstractProperty::AbstractProperty(const std::string& name, const std::string& title)
: _name(name)
, _title(title)
, _invalidationLevel(invalidationLevel)
{
_isVisible = true;
_inUse = 0;
......@@ -49,14 +48,6 @@ namespace campvis {
return _title;
}
int AbstractProperty::getInvalidationLevel() const {
return _invalidationLevel;
}
void AbstractProperty::setInvalidationLevel(int il) {
_invalidationLevel = il;
}
void AbstractProperty::addSharedProperty(AbstractProperty* prop) {
tgtAssert(prop != 0, "Shared property must not be 0!");
tgtAssert(prop != this, "Shared property must not be this!");
......
......@@ -49,9 +49,8 @@ namespace campvis {
* Creates a new AbstractProperty
* \param name Property name (unchangable!)
* \param title Property title (e.g. used for GUI)
* \param invalidationLevel Invalidation level that this property triggers
*/
AbstractProperty(const std::string& name, const std::string& title, int invalidationLevel = AbstractProcessor::INVALID_RESULT);
AbstractProperty(const std::string& name, const std::string& title);
/**
* Virtual Destructor
......@@ -82,19 +81,7 @@ namespace campvis {
* \return _title
*/
const std::string& getTitle() const;
/**
* Returns the invalidation level that this property triggers.
* \return _invalidationLevel
*/
int getInvalidationLevel() const;
/**
* Sets the invalidation level that this property triggers.
* \param il New invalidation level that this property triggers.
*/
void setInvalidationLevel(int il);
/**
* Returns whether this proberty shall be visible in the GUI.
* \return _isVisible
......@@ -155,7 +142,6 @@ namespace campvis {
// DO NOT REMOVE THE CONSTNESS OF _name. PropertyCollection relies on it!
const std::string _name; ///< Property name (unchangable on purpose!)
std::string _title; ///< Property title (e.g. used for GUI)
int _invalidationLevel; ///< Invalidation level that this property triggers
tbb::atomic<bool> _isVisible; ///< Flag whether this property shall be visible in the GUI
tbb::atomic<int> _inUse; ///< flag whether property is currently in use and values are written to back buffer
......@@ -168,6 +154,7 @@ namespace campvis {
*/
std::set<AbstractProperty*> _sharedProperties;
private:
static const std::string loggerCat_;
};
......
......@@ -28,8 +28,8 @@ namespace campvis {
const std::string ButtonProperty::loggerCat_ = "CAMPVis.core.datastructures.ButtonProperty";
ButtonProperty::ButtonProperty(const std::string& name, const std::string& title, int invalidationLevel /*= AbstractProcessor::INVALID_RESULT*/)
: AbstractProperty(name, title, invalidationLevel)
ButtonProperty::ButtonProperty(const std::string& name, const std::string& title)
: AbstractProperty(name, title)
{
}
......
......@@ -37,9 +37,8 @@ namespace campvis {
* Creates a new ButtonProperty
* \param name Property name (unchangable!)
* \param title Property title (e.g. used for GUI)
* \param invalidationLevel Invalidation level that this property triggers
*/
ButtonProperty(const std::string& name, const std::string& title, int invalidationLevel = AbstractProcessor::INVALID_RESULT);
ButtonProperty(const std::string& name, const std::string& title);
/**
* Virtual Destructor
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment