Commit fc707dcd authored by schultezub's avatar schultezub
Browse files

Revised InvalidationLevel concept: InvalidationLevels now directly belong to...

Revised InvalidationLevel concept: InvalidationLevels now directly belong to an AbstractProcessor and are considered to be thread-safe. Furthermore the different levels now really act as single flags that are set (invalid) or unset (valid) individually.

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@464 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent bab66780
......@@ -144,10 +144,12 @@ namespace campvis {
if (_selectedProcessor != 0 && _selectedPipeline != 0) {
// this is not as trivial as it seems:
// We need the pipeline, probably an OpenGL context...
_selectedProcessor->applyInvalidationLevel(InvalidationLevel::INVALID_RESULT);
_selectedProcessor->invalidate(AbstractProcessor::INVALID_RESULT);
}
else if (_selectedPipeline != 0) {
for (std::vector<AbstractProcessor*>::const_iterator it = _selectedPipeline->getProcessors().begin(); it != _selectedPipeline->getProcessors().end(); ++it) {
(*it)->invalidate(AbstractProcessor::INVALID_RESULT);
}
}
}
......
......@@ -101,7 +101,7 @@ namespace campvis {
void AbstractPipeline::executeProcessor(AbstractProcessor* processor) {
tgtAssert(processor != 0, "Processor must not be 0.");
if (processor->getEnabled() && !processor->isLocked() && !processor->getInvalidationLevel().isValid()) {
if (processor->getEnabled() && !processor->isLocked() && processor->hasInvalidResult()) {
processor->lockProcessor();
#ifdef CAMPVIS_DEBUG
clock_t startTime = clock();
......
......@@ -30,6 +30,7 @@
#include "tbb/compat/thread"
#include "tgt/assert.h"
#include "abstractprocessor.h"
#include "core/properties/abstractproperty.h"
namespace campvis {
......@@ -41,28 +42,13 @@ namespace campvis {
{
_enabled = true;
_locked = 0;
_level = VALID;
}
AbstractProcessor::~AbstractProcessor() {
}
const InvalidationLevel& AbstractProcessor::getInvalidationLevel() const {
return _invalidationLevel;
}
void AbstractProcessor::applyInvalidationLevel(InvalidationLevel il) {
_invalidationLevel.setLevel(il);
// If processor is no longer valid, notify observers
if (! _invalidationLevel.isValid()) {
s_invalidated(this);
}
else {
s_validated(this);
}
}
void AbstractProcessor::init() {
initAllProperties();
}
......@@ -91,7 +77,7 @@ namespace campvis {
void AbstractProcessor::onPropertyChanged(const AbstractProperty* prop) {
HasPropertyCollection::onPropertyChanged(prop);
applyInvalidationLevel(prop->getInvalidationLevel());
invalidate(prop->getInvalidationLevel());
}
bool AbstractProcessor::getEnabled() const {
......@@ -102,5 +88,21 @@ namespace campvis {
_enabled = enabled;
}
void AbstractProcessor::invalidate(int level) {
int tmp;
do {
tmp = _level;
} while (_level.compare_and_swap(tmp | level, tmp) != tmp);
s_invalidated(this);
}
void AbstractProcessor::validate(int level) {
int tmp;
do {
tmp = _level;
} while (_level.compare_and_swap(tmp & (~level), tmp) != tmp);
s_validated(this);
}
}
......@@ -34,7 +34,6 @@
#include "tbb/atomic.h"
#include "tgt/logmanager.h"
#include "core/datastructures/datacontainer.h"
#include "core/tools/invalidationlevel.h"
#include "core/properties/propertycollection.h"
#include <string>
......@@ -57,17 +56,17 @@ namespace campvis {
* \sa AbstractPipeline
*/
class AbstractProcessor : public HasPropertyCollection {
/**
* We have to find a trade-off:
* On the one hand, we want to follow the information-hiding concept and keep the processor's
* properties private. On the other hand pipelines will usually want direct access to them
* (e.g. in order to setup data IDs or property sharing) and the properties in the PropertyCollection
* are not strongly typed. Hence, we declare AbstractPipeline as our friend.
*/
friend class AbstractPipeline; // TODO: this does not work as intended...
public:
/**
* Available invalidation levels
*/
enum InvalidationLevel {
VALID = 0, ///< Valid
INVALID_RESULT = 1 << 0, ///< Need to rerun the process() method
INVALID_SHADER = 1 << 1, ///< Need to recompile the shader
INVALID_FILE = 1 << 2, ///< Need to reread the file
INVALID_PROPERTIES = 1 << 3 ///< Need to update the properties
};
/**
* Creates a AbstractProcessor.
......@@ -100,12 +99,6 @@ namespace campvis {
**/
virtual void process(DataContainer& data) = 0;
/**
* Returns the invalidation level of this processor.
* \return _invalidationLevel
*/
const InvalidationLevel& getInvalidationLevel() const;
/**
* Gets the name of this very processor. To be defined by every subclass.
* \return The name of this processor.
......@@ -118,14 +111,6 @@ namespace campvis {
*/
virtual const std::string getDescription() const = 0;
/**
* Update the processor's invalidation level by \a il.
* If \a il is VALID, the processor's invalidation level will be set to VALID.
* If \a il is one of the INVALID_X state, the processor's corresponding flag will be set.
* \param il Invalidation level to apply.
*/
void applyInvalidationLevel(InvalidationLevel il);
/**
* Gets the flag whether this processor is currently enabled.
* \return _enabled
......@@ -158,19 +143,105 @@ namespace campvis {
*/
bool isLocked();
// = Invalidation Level related stuff =============================================================
/**
* Returns the current invalidation level.
* \return _level
*/
int getInvalidationLevel() const {
return _level;
}
/**
* Returns wheter the invalidation level is valid (i.e. no invalid flag is set).
* \return _level == VALID
*/
bool isValid() const {
return _level == static_cast<int>(VALID);
}
/**
* Returns wheter the the INVALID_RESULT flag is set.
* \return _level & INVALID_RESULT
*/
bool hasInvalidResult() const {
return (_level & static_cast<int>(INVALID_RESULT)) != 0;
}
/**
* Returns wheter the the INVALID_SHADER flag is set.
* \return _level & INVALID_SHADER
*/
bool hasInvalidShader() const {
return (_level & static_cast<int>(INVALID_SHADER)) != 0;
}
/**
* Returns wheter the the INVALID_FILE flag is set.
* \return _level & INVALID_FILE
*/
bool hasInvalidFile() const {
return (_level & static_cast<int>(INVALID_FILE)) != 0;
}
/**
* Returns wheter the the INVALID_PROPERTIES flag is set.
* \return _level & INVALID_PROPERTIES
*/
bool hasInvalidProperties() const {
return (_level & static_cast<int>(INVALID_PROPERTIES)) != 0;
}
/**
* Sets the invalidation level to valid (i.e. clears all invalidation flags).
*/
void setValid() {
_level = static_cast<int>(VALID);
}
/**
* Sets all invalidation flags specified in \a level.
* \param level Flags to set to invalid.
*/
void invalidate(int level);
/**
* Sets all invalidation flags specified in \a il's level.
* \param il Flags to set to invalid.
*/
void invalidate(InvalidationLevel il) {
invalidate(static_cast<int>(il));
}
/**
* Clears all invalidation flags specified in \a level.
* \param level Flags to set to valid.
*/
void validate(int level);
/**
* Clears all invalidation flags specified in \a il's level.
* \param il Flags to set to valid.
*/
void validate(InvalidationLevel il) {
validate(static_cast<int>(il));
}
/// Signal emitted when the processor has been invalidated.
sigslot::signal1<AbstractProcessor*> s_invalidated;
/// Signal emitted when the processor has been validated.
sigslot::signal1<AbstractProcessor*> s_validated;
// = Slots ========================================================================================
/**
* Slot getting called when one of the observed properties changed and notifies its observers.
* \param prop Property that emitted the signal
*/
virtual void onPropertyChanged(const AbstractProperty* prop);
protected:
tbb::atomic<bool> _enabled; ///< flag whether this processor is currently enabled
......@@ -178,11 +249,10 @@ namespace campvis {
/// (This implies, that all properties are locked and it is not valid to call process())
tbb::atomic<bool> _locked;
static const std::string loggerCat_;
private:
InvalidationLevel _invalidationLevel; ///< current invalidation level of this processor
tbb::atomic<int> _level; ///< current invalidation level
static const std::string loggerCat_;
};
}
......
......@@ -36,7 +36,7 @@ namespace campvis {
ProcessorDecoratorMasking::ProcessorDecoratorMasking()
: AbstractProcessorDecorator()
, _applyMask("applyMask", "Apply Mask to image", false, InvalidationLevel::INVALID_SHADER)
, _applyMask("applyMask", "Apply Mask to image", false, AbstractProcessor::INVALID_SHADER)
, _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)
......
......@@ -36,8 +36,8 @@ namespace campvis {
ProcessorDecoratorShading::ProcessorDecoratorShading(const std::string& lightUniformName /*= "_lightSource"*/)
: AbstractProcessorDecorator()
, _enableShading("EnableShading", "Enable Shading", true, InvalidationLevel::INVALID_SHADER)
, _centralDifferences("CentralDifferences", "Use Central instead of Forward Differences", false, InvalidationLevel::INVALID_SHADER)
, _enableShading("EnableShading", "Enable Shading", true, AbstractProcessor::INVALID_SHADER)
, _centralDifferences("CentralDifferences", "Use Central instead of Forward Differences", false, AbstractProcessor::INVALID_SHADER)
, _lightPosition("LightPosition", "Light Position", tgt::vec3(-8.f), tgt::vec3(-500.f), tgt::vec3(500.f))
, _ambientColor("AmbientColor", "Ambient Light Color", tgt::vec3(0.5f), 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))
......
......@@ -98,9 +98,10 @@ namespace campvis {
p_transferFunction.getTF()->setImageHandle(img.getDataHandle());
}
if (getInvalidationLevel().isInvalidShader()) {
if (hasInvalidShader()) {
_shader->setHeaders(generateHeader());
_shader->rebuild();
validate(INVALID_SHADER);
}
glPushAttrib(GL_ALL_ATTRIB_BITS);
......@@ -157,7 +158,7 @@ namespace campvis {
LERROR("No suitable input image found.");
}
applyInvalidationLevel(InvalidationLevel::VALID);
validate(INVALID_RESULT);
}
std::string RaycastingProcessor::generateHeader() const {
......
......@@ -33,10 +33,10 @@ namespace campvis {
const std::string AbstractProperty::loggerCat_ = "CAMPVis.core.datastructures.AbstractProperty";
AbstractProperty::AbstractProperty(const std::string& name, const std::string& title, InvalidationLevel il /*= InvalidationLevel::INVALID_RESULT*/)
AbstractProperty::AbstractProperty(const std::string& name, const std::string& title, int invalidationLevel /*= AbstractProcessor::INVALID_RESULT*/)
: _name(name)
, _title(title)
, _invalidationLevel(il)
, _invalidationLevel(invalidationLevel)
{
_isVisible = true;
_inUse = 0;
......@@ -53,11 +53,11 @@ namespace campvis {
return _title;
}
const InvalidationLevel& AbstractProperty::getInvalidationLevel() const {
int AbstractProperty::getInvalidationLevel() const {
return _invalidationLevel;
}
void AbstractProperty::setInvalidationLevel(const InvalidationLevel& il) {
void AbstractProperty::setInvalidationLevel(AbstractProcessor::InvalidationLevel il) {
_invalidationLevel = il;
}
......
......@@ -34,7 +34,7 @@
#include "tbb/atomic.h"
#include "tbb/spin_mutex.h"
#include "tgt/logmanager.h"
#include "core/tools/invalidationlevel.h"
#include "core/pipeline/abstractprocessor.h"
#include <set>
#include <string>
......@@ -52,9 +52,9 @@ namespace campvis {
* Creates a new AbstractProperty
* \param name Property name (unchangable!)
* \param title Property title (e.g. used for GUI)
* \param il Invalidation level that this property triggers
* \param invalidationLevel Invalidation level that this property triggers
*/
AbstractProperty(const std::string& name, const std::string& title, InvalidationLevel il = InvalidationLevel::INVALID_RESULT);
AbstractProperty(const std::string& name, const std::string& title, int invalidationLevel = AbstractProcessor::INVALID_RESULT);
/**
* Virtual Destructor
......@@ -90,13 +90,13 @@ namespace campvis {
* Returns the invalidation level that this property triggers.
* \return _invalidationLevel
*/
const InvalidationLevel& getInvalidationLevel() const;
int getInvalidationLevel() const;
/**
* Sets the invalidation level that this property triggers.
* \param il New invalidation level that this property triggers.
*/
void setInvalidationLevel(const InvalidationLevel& il);
void setInvalidationLevel(AbstractProcessor::InvalidationLevel il);
/**
* Returns whether this proberty shall be visible in the GUI.
......@@ -158,7 +158,7 @@ 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)
InvalidationLevel _invalidationLevel; ///< Invalidation level that this property triggers
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
......
......@@ -33,8 +33,8 @@ namespace campvis {
const std::string CameraProperty::loggerCat_ = "CAMPVis.core.datastructures.CameraProperty";
CameraProperty::CameraProperty(const std::string& name, const std::string& title, tgt::Camera cam /*= tgt::Camera()*/, InvalidationLevel il /*= InvalidationLevel::INVALID_RESULT*/)
: GenericProperty<tgt::Camera>(name, title, cam, il)
CameraProperty::CameraProperty(const std::string& name, const std::string& title, tgt::Camera cam /*= tgt::Camera()*/, int invalidationLevel /*= AbstractProcessor::INVALID_RESULT*/)
: GenericProperty<tgt::Camera>(name, title, cam, invalidationLevel)
{
}
......
......@@ -42,9 +42,9 @@ namespace campvis {
* \param name Property name (unchangable!)
* \param title Property title (e.g. used for GUI)
* \param cam Camera to initialize the property with
* \param il Invalidation level that this property triggers
* \param invalidationLevel Invalidation level that this property triggers
*/
CameraProperty(const std::string& name, const std::string& title, tgt::Camera cam = tgt::Camera(), InvalidationLevel il = InvalidationLevel::INVALID_RESULT);
CameraProperty(const std::string& name, const std::string& title, tgt::Camera cam = tgt::Camera(), int invalidationLevel = AbstractProcessor::INVALID_RESULT);
/**
* Virtual Destructor
......
......@@ -33,8 +33,8 @@ namespace campvis {
const std::string DataNameProperty::loggerCat_ = "CAMPVis.core.datastructures.DataNameProperty";
DataNameProperty::DataNameProperty(const std::string& name, const std::string& title, const std::string& value, DataAccessInfo access, InvalidationLevel il /*= InvalidationLevel::INVALID_RESULT*/)
: GenericProperty<std::string>(name, title, value, il)
DataNameProperty::DataNameProperty(const std::string& name, const std::string& title, const std::string& value, DataAccessInfo access, int invalidationLevel /*= AbstractProcessor::INVALID_RESULT*/)
: GenericProperty<std::string>(name, title, value, invalidationLevel)
, _accessInfo(access)
{
......
......@@ -54,9 +54,9 @@ namespace campvis {
* \param title Property title (e.g. used for GUI)
* \param value Initial value
* \param access DataAccessInfo flag defining whether processor will read or write from/to the DataHandle with the given ID.
* \param il Invalidation level that this property triggers
* \param invalidationLevel Invalidation level that this property triggers
*/
DataNameProperty(const std::string& name, const std::string& title, const std::string& value, DataAccessInfo access, InvalidationLevel il = InvalidationLevel::INVALID_RESULT);
DataNameProperty(const std::string& name, const std::string& title, const std::string& value, DataAccessInfo access, int invalidationLevel = AbstractProcessor::INVALID_RESULT);
/**
* Virtual Destructor
......
......@@ -50,13 +50,13 @@ namespace campvis {
* \param name Property name
* \param title Property title (e.g. used for GUI)
* \param value Initial value of the property
* \param il Invalidation level that this property triggers
* \param invalidationLevel Invalidation level that this property triggers
*/
GenericProperty(
const std::string& name,
const std::string& title,
const T& value,
InvalidationLevel il = InvalidationLevel::INVALID_RESULT);
int invalidationLevel = AbstractProcessor::INVALID_RESULT);
/**
* Virtual Destructor
......@@ -133,8 +133,8 @@ namespace campvis {
// = Template Implementation ======================================================================
template<typename T>
campvis::GenericProperty<T>::GenericProperty(const std::string& name, const std::string& title, const T& value, InvalidationLevel il /*= InvalidationLevel::INVALID_RESULT*/)
: AbstractProperty(name, title, il)
campvis::GenericProperty<T>::GenericProperty(const std::string& name, const std::string& title, const T& value, int invalidationLevel /*= AbstractProcessor::INVALID_RESULT*/)
: AbstractProperty(name, title, invalidationLevel)
, _value(value)
, _backBuffer(value)
{
......
......@@ -107,7 +107,7 @@ namespace campvis {
* \param value Initial value of the property
* \param minValue Minimum value for this property
* \param maxValue Maximum value for this property
* \param il Invalidation level that this property triggers
* \param invalidationLevel Invalidation level that this property triggers
*/
NumericProperty(
const std::string& name,
......@@ -115,7 +115,7 @@ namespace campvis {
const T& value,
const T& minValue,
const T& maxValue,
InvalidationLevel il = InvalidationLevel::INVALID_RESULT);
int invalidationLevel = AbstractProcessor::INVALID_RESULT);
/**
* Virtual Destructor
......@@ -202,8 +202,8 @@ namespace campvis {
// = Template Implementation ======================================================================
template<typename T>
campvis::NumericProperty<T>::NumericProperty(const std::string& name, const std::string& title, const T& value, const T& minValue, const T& maxValue, InvalidationLevel il /*= InvalidationLevel::INVALID_RESULT*/)
: GenericProperty<T>(name, title, value, il)
campvis::NumericProperty<T>::NumericProperty(const std::string& name, const std::string& title, const T& value, const T& minValue, const T& maxValue, int invalidationLevel /*= AbstractProcessor::INVALID_RESULT*/)
: GenericProperty<T>(name, title, value, invalidationLevel)
, _minValue(minValue)
, _maxValue(maxValue)
{
......
......@@ -47,10 +47,10 @@ namespace campvis {
* Creates a new AbstractOptionProperty.
* \param name Property name
* \param title Property title (e.g. used for GUI)
* \param il Invalidation level that this property triggers
* \param invalidationLevel Invalidation level that this property triggers
*/
AbstractOptionProperty(const std::string& name, const std::string& title, InvalidationLevel il = InvalidationLevel::INVALID_RESULT)
: IntProperty(name, title, -1, -1, -1, il)
AbstractOptionProperty(const std::string& name, const std::string& title, int invalidationLevel = AbstractProcessor::INVALID_RESULT)
: IntProperty(name, title, -1, -1, -1, invalidationLevel)
{
};
......@@ -107,14 +107,14 @@ namespace campvis {
* \param title Property title (e.g. used for GUI)
* \param options Array of the options for this property, must not be 0, must not be empty.
* \param count Number of items in \a options (number of options), must be greater 0.
* \param il Invalidation level that this property triggers
* \param invalidationLevel Invalidation level that this property triggers
*/
GenericOptionProperty(
const std::string& name,
const std::string& title,
const GenericOption<T>* options,
size_t count,
InvalidationLevel il = InvalidationLevel::INVALID_RESULT);
int invalidationLevel = AbstractProcessor::INVALID_RESULT);
/**
* Destructor
......@@ -164,8 +164,8 @@ namespace campvis {
// = Template Implementation ======================================================================
template<typename T>
campvis::GenericOptionProperty<T>::GenericOptionProperty(const std::string& name, const std::string& title, const GenericOption<T>* options, size_t count, InvalidationLevel il /*= InvalidationLevel::INVALID_RESULT*/)
: AbstractOptionProperty(name, title, il)
campvis::GenericOptionProperty<T>::GenericOptionProperty(const std::string& name, const std::string& title, const GenericOption<T>* options, size_t count, int invalidationLevel /*= AbstractProcessor::INVALID_RESULT*/)
: AbstractOptionProperty(name, title, invalidationLevel)
{
tgtAssert(options != 0, "Pointer to options array must not be 0.")
tgtAssert(count > 0, "The number of options must be greater 0.");
......
......@@ -28,6 +28,7 @@
// ================================================================================================
#include "propertycollection.h"
#include "core/properties/abstractproperty.h"
namespace campvis {
HasPropertyCollection::HasPropertyCollection() {
......@@ -116,7 +117,7 @@ namespace campvis {
}
void HasPropertyCollection::onPropertyChanged(const AbstractProperty* prop) {
if (prop->getInvalidationLevel().isInvalidProperties())
if (prop->getInvalidationLevel() & AbstractProcessor::INVALID_PROPERTIES)
updateProperties();
}
......
......@@ -31,13 +31,13 @@
#define PROPERTYCOLLECTION_H__
#include "sigslot/sigslot.h"
#include "core/properties/abstractproperty.h"
#include <vector>
#include <string>
namespace campvis {
class AbstractProperty;
/// A PropertyCollection wraps around a bunch of properties - currently its just a typedef...
typedef std::vector<AbstractProperty*> PropertyCollection;
......
......@@ -33,8 +33,8 @@ namespace campvis {
const std::string TransferFunctionProperty::loggerCat_ = "CAMPVis.core.datastructures.TransferFunctionProperty";
TransferFunctionProperty::TransferFunctionProperty(const std::string& name, const std::string& title, AbstractTransferFunction* tf, InvalidationLevel il /*= InvalidationLevel::INVALID_RESULT*/)
: AbstractProperty(name, title, il)
TransferFunctionProperty::TransferFunctionProperty(const std::string& name, const std::string& title, AbstractTransferFunction* tf, int invalidationLevel /*= AbstractProcessor::INVALID_RESULT*/)
: AbstractProperty(name, title, invalidationLevel)
, _transferFunction(tf)
{
tgtAssert(tf != 0, "Assigned transfer function must not be 0.");
......
......@@ -46,9 +46,9 @@ namespace campvis {
* \param name Property name (unchangable!)
* \param title Property title (e.g. used for GUI)
* \param tf Transfer function to initialize the property with.
* \param il Invalidation level that this property triggers
* \param invalidationLevel Invalidation level that this property triggers
*/
TransferFunctionProperty(const std::string& name, const std::string& title, AbstractTransferFunction* tf, InvalidationLevel il = InvalidationLevel::INVALID_RESULT);
TransferFunctionProperty(const std::string& name, const std::string& title, AbstractTransferFunction* tf, int invalidationLevel = AbstractProcessor::INVALID_RESULT);