Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
9.2.2023: Due to updates GitLab will be unavailable for some minutes between 9:00 and 11:00.
Open sidebar
CAMP
campvis-public
Commits
67cb4073
Commit
67cb4073
authored
Oct 08, 2013
by
Christian Schulte zu Berge
Browse files
Refactoring pipeline concept
#3
: Introducing PipelineFactory and PipelineRegistrar
parent
2d55cb00
Changes
31
Hide whitespace changes
Inline
Side-by-side
application/campvis.cpp
View file @
67cb4073
...
...
@@ -66,23 +66,23 @@ int main(int argc, char** argv) {
#endif
CampVisApplication
app
(
argc
,
argv
);
// app.addVisualizationPipeline("Advanced Ultrasound Visualization", new AdvancedUsVis());
// app.addVisualizationPipeline("Confidence Map Generation", new CmBatchGeneration());
// app.addVisualizationPipeline("IXPV", new IxpvDemo());
app
.
addVisualizationPipeline
(
"SliceVis"
,
new
SliceVis
());
// app.addVisualizationPipeline("DVRVis", new DVRVis());
// app.addVisualizationPipeline("VolumeRendererDemo", new VolumeRendererDemo());
app
.
addVisualizationPipeline
(
"VolumeExplorerDemo"
,
new
VolumeExplorerDemo
());
// app.addVisualizationPipeline("Advanced Ultrasound Visualization", new AdvancedUsVis(
app.getDataContainer()
));
// app.addVisualizationPipeline("Confidence Map Generation", new CmBatchGeneration(
app.getDataContainer()
));
// app.addVisualizationPipeline("IXPV", new IxpvDemo(
app.getDataContainer()
));
app
.
addVisualizationPipeline
(
"SliceVis"
,
new
SliceVis
(
app
.
getDataContainer
()
));
// app.addVisualizationPipeline("DVRVis", new DVRVis(
app.getDataContainer()
));
// app.addVisualizationPipeline("VolumeRendererDemo", new VolumeRendererDemo(
app.getDataContainer()
));
app
.
addVisualizationPipeline
(
"VolumeExplorerDemo"
,
new
VolumeExplorerDemo
(
app
.
getDataContainer
()
));
#ifdef HAS_KISSCL
// app.addVisualizationPipeline("DVR with OpenCL", new OpenCLPipeline());
// app.addVisualizationPipeline("DVR with OpenCL", new OpenCLPipeline(
app.getDataContainer()
));
#endif
#ifdef CAMPVIS_HAS_MODULE_SCR_MSK
app
.
addVisualizationPipeline
(
"US Compounding"
,
new
UsCompounding
());
app
.
addVisualizationPipeline
(
"US Compounding"
,
new
UsCompounding
(
app
.
getDataContainer
()
));
#endif
#ifdef CAMPVIS_HAS_MODULE_COLUMBIA
app
.
addVisualizationPipeline
(
"Columbia"
,
new
Columbia1
());
app
.
addVisualizationPipeline
(
"Columbia"
,
new
Columbia1
(
app
.
getDataContainer
()
));
#endif
...
...
application/campvisapplication.cpp
View file @
67cb4073
...
...
@@ -50,6 +50,7 @@
#include
"core/tools/quadrenderer.h"
#include
"core/pipeline/abstractpipeline.h"
#include
"core/pipeline/autoevaluationpipeline.h"
#include
"core/pipeline/pipelinefactory.h"
namespace
campvis
{
...
...
@@ -173,6 +174,8 @@ namespace campvis {
GLJobProc
.
start
();
_initialized
=
true
;
LINFO
(
PipelineFactory
::
getRef
().
toString
());
}
void
CampVisApplication
::
deinit
()
{
...
...
@@ -270,4 +273,12 @@ namespace campvis {
_mainWindow
->
addDockWidget
(
area
,
dock
);
}
DataContainer
*
CampVisApplication
::
getDataContainer
()
{
return
&
_dataContainer
;
}
const
DataContainer
*
CampVisApplication
::
getDataContainer
()
const
{
return
&
_dataContainer
;
}
}
application/campvisapplication.h
View file @
67cb4073
...
...
@@ -38,6 +38,8 @@
#include
<utility>
#include
<vector>
#include
"core/datastructures/datacontainer.h"
namespace
tgt
{
class
QtThreadedCanvas
;
}
...
...
@@ -125,10 +127,25 @@ namespace campvis {
*/
int
run
();
/**
* Gets the DataContainer of this CampvisApplication
* \return _dataContainer
*/
DataContainer
*
getDataContainer
();
/**
* Gets the DataContainer of this CampvisApplication
* \return _dataContainer
*/
const
DataContainer
*
getDataContainer
()
const
;
/// Signal emitted when the collection of pipelines has changed.
sigslot
::
signal0
<>
s_PipelinesChanged
;
private:
/// The (currently) one and only DataContainer in CampvisApplication
DataContainer
_dataContainer
;
/// All pipelines (incuding VisualizationPipelines)
std
::
vector
<
AbstractPipeline
*>
_pipelines
;
/// All visualisations (i.e. VisualizationPipelines with their corresponding painters/canvases)
...
...
core/pipeline/abstractpipeline.cpp
View file @
67cb4073
...
...
@@ -34,8 +34,8 @@
#include
"tgt/glcontext.h"
#include
"tgt/tgt_gl.h"
#include
"core/pipeline/abstractprocessor.h"
#include
"core/pipeline/visualizationprocessor.h"
#include
"core/pipeline/abstractprocessor.h"
#include
"core/tools/job.h"
#include
"core/tools/opengljobprocessor.h"
#include
"core/tools/simplejobprocessor.h"
...
...
@@ -67,15 +67,18 @@ namespace {
namespace
campvis
{
const
std
::
string
AbstractPipeline
::
loggerCat_
=
"CAMPVis.core.datastructures.AbstractPipeline"
;
AbstractPipeline
::
AbstractPipeline
()
AbstractPipeline
::
AbstractPipeline
(
DataContainer
*
dc
)
:
HasPropertyCollection
()
,
tgt
::
EventHandler
()
,
tgt
::
EventListener
()
,
_data
(
dc
)
,
_canvas
(
0
)
,
_canvasSize
(
"CanvasSize"
,
"Canvas Size"
,
tgt
::
ivec2
(
128
,
128
),
tgt
::
ivec2
(
1
,
1
),
tgt
::
ivec2
(
4096
,
4096
))
,
_ignoreCanvasSizeUpdate
(
false
)
,
_renderTargetID
(
"renderTargetID"
,
"Render Target ID"
,
"AbstractPipeline.renderTarget"
,
DataNameProperty
::
READ
)
{
tgtAssert
(
_data
!=
0
,
"Pointer to the DataContainer for this pipeline must not be 0!"
);
_enabled
=
true
;
addProperty
(
&
_renderTargetID
);
...
...
@@ -87,7 +90,7 @@ namespace campvis {
void
AbstractPipeline
::
init
()
{
_renderTargetID
.
s_changed
.
connect
<
AbstractPipeline
>
(
this
,
&
AbstractPipeline
::
onPropertyChanged
);
_data
.
s_dataAdded
.
connect
(
this
,
&
AbstractPipeline
::
onDataContainerDataAdded
);
_data
->
s_dataAdded
.
connect
(
this
,
&
AbstractPipeline
::
onDataContainerDataAdded
);
initAllProperties
();
...
...
@@ -116,11 +119,11 @@ namespace campvis {
}
}
_data
.
s_dataAdded
.
disconnect
(
this
);
_data
->
s_dataAdded
.
disconnect
(
this
);
_renderTargetID
.
s_changed
.
disconnect
(
this
);
// clear DataContainer
_data
.
clear
();
_data
->
clear
();
}
void
AbstractPipeline
::
onPropertyChanged
(
const
AbstractProperty
*
prop
)
{
...
...
@@ -140,11 +143,11 @@ namespace campvis {
}
const
DataContainer
&
AbstractPipeline
::
getDataContainer
()
const
{
return
_data
;
return
*
_data
;
}
DataContainer
&
AbstractPipeline
::
getDataContainer
()
{
return
_data
;
return
*
_data
;
}
void
AbstractPipeline
::
executeProcessor
(
AbstractProcessor
*
processor
,
bool
unlockInExtraThred
)
{
...
...
@@ -153,7 +156,7 @@ namespace campvis {
if
(
processor
->
getEnabled
()
&&
!
processor
->
isLocked
())
{
// update properties if they're invalid
if
(
processor
->
hasInvalidProperties
())
{
processor
->
updateProperties
(
_data
);
processor
->
updateProperties
(
*
_data
);
#if CAMPVIS_DEBUG
if
(
processor
->
hasInvalidProperties
())
LDEBUG
(
"Processor "
<<
processor
->
getName
()
<<
" still has INVALID_PROPERTIES level. Did you forget to validate the processor in updateProperties()?"
);
...
...
@@ -166,7 +169,7 @@ namespace campvis {
clock_t
startTime
=
clock
();
try
{
processor
->
process
(
_data
);
processor
->
process
(
*
_data
);
}
catch
(
std
::
exception
&
e
)
{
LERROR
(
"Caught unhandled exception while executing processor "
<<
processor
->
getName
()
<<
": "
<<
e
.
what
());
...
...
core/pipeline/abstractpipeline.h
View file @
67cb4073
...
...
@@ -45,6 +45,7 @@
#include
"core/properties/floatingpointproperty.h"
#include
"core/properties/propertycollection.h"
#include
<map>
#include
<vector>
namespace
tgt
{
...
...
@@ -63,8 +64,11 @@ namespace campvis {
* Creates a AbstractPipeline.
* If you derive from AbstractPipeline, you will have to implement the pipeline evaluation
* logic yourself. You might want to have a look at AutoEvaluationPipeline.
*
* \param dc Pointer to the DataContainer containing local working set of data for this
* pipeline, must not be 0, must be valid the whole lifetime of this pipeline.
*/
AbstractPipeline
();
AbstractPipeline
(
DataContainer
*
dc
);
/**
* Virtual Destructor
...
...
@@ -213,7 +217,8 @@ namespace campvis {
virtual
void
onPropertyChanged
(
const
AbstractProperty
*
prop
);
DataContainer
_data
;
///< DataContainer containing local working set of data for this Pipeline
/// Pointer to the DataContainer containing local working set of data for this Pipeline, must not be 0.
DataContainer
*
_data
;
std
::
vector
<
AbstractProcessor
*>
_processors
;
///< List of all processors of this pipeline
tbb
::
atomic
<
bool
>
_enabled
;
///< flag whether this pipeline is currently enabled
...
...
core/pipeline/autoevaluationpipeline.cpp
View file @
67cb4073
...
...
@@ -40,8 +40,8 @@
namespace
campvis
{
const
std
::
string
AutoEvaluationPipeline
::
loggerCat_
=
"CAMPVis.core.datastructures.AutoEvaluationPipeline"
;
AutoEvaluationPipeline
::
AutoEvaluationPipeline
()
:
AbstractPipeline
()
AutoEvaluationPipeline
::
AutoEvaluationPipeline
(
DataContainer
*
dc
)
:
AbstractPipeline
(
dc
)
{
}
...
...
core/pipeline/autoevaluationpipeline.h
View file @
67cb4073
...
...
@@ -41,13 +41,16 @@ namespace campvis {
* Specializtaion of AbstractPipeline performing automatic execution of invalidated processors.
* AutoEvaluationPipeline connects to the s_(in)validated signals of all of its processors and
* executes processors with invalid results using the correct threads.
*
* \param dc Pointer to the DataContainer containing local working set of data for this
* pipeline, must not be 0, must be valid the whole lifetime of this pipeline.
*/
class
AutoEvaluationPipeline
:
public
AbstractPipeline
{
public:
/**
* Creates a AutoEvaluationPipeline.
*/
AutoEvaluationPipeline
();
AutoEvaluationPipeline
(
DataContainer
*
dc
);
/**
* Virtual Destructor
...
...
core/pipeline/digraphvisualizationpipeline.cpp
deleted
100644 → 0
View file @
2d55cb00
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universitt Mnchen
// Boltzmannstr. 3, 85748 Garching b. Mnchen, Germany
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// The licensing of this softare is not yet resolved. Until then, redistribution in source or
// binary forms outside the CAMP chair is not permitted, unless explicitly stated in legal form.
// However, the names of the original authors and the above copyright notice must retain in its
// original state in any case.
//
// Legal disclaimer provided by the BSD license:
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// ================================================================================================
#include
"digraphvisualizationpipeline.h"
#include
"tgt/tgt_gl.h"
#include
"tgt/glcanvas.h"
#include
"tgt/glcontext.h"
#include
"core/pipeline/visualizationprocessor.h"
#include
"core/tools/job.h"
#include
"core/tools/opengljobprocessor.h"
#include
"core/tools/simplejobprocessor.h"
#include
<stack>
namespace
campvis
{
const
std
::
string
DigraphVisualizationPipeline
::
loggerCat_
=
"CAMPVis.core.datastructures.DigraphVisualizationPipeline"
;
DigraphVisualizationPipeline
::
DependencyNode
::
DependencyNode
(
AbstractProcessor
*
processor
)
:
_processor
(
processor
)
{
tgtAssert
(
_processor
!=
0
,
"Processor must not be 0."
);
if
(
_processor
!=
0
)
{
_isVisualizationProcessor
=
(
dynamic_cast
<
VisualizationProcessor
*>
(
_processor
)
!=
0
);
}
}
void
DigraphVisualizationPipeline
::
DependencyNode
::
addDependency
(
DependencyNode
*
dependency
)
{
tgtAssert
(
dependency
!=
0
,
"DependencyNode must not be 0."
);
// check for acyclicness
std
::
stack
<
DependencyNode
*>
nodesToVisit
;
for
(
std
::
set
<
DependencyNode
*>::
const_iterator
it
=
dependency
->
_dependentNodes
.
begin
();
it
!=
dependency
->
_dependentNodes
.
end
();
++
it
)
{
nodesToVisit
.
push
(
*
it
);
}
while
(
!
nodesToVisit
.
empty
())
{
DependencyNode
*
node
=
nodesToVisit
.
top
();
nodesToVisit
.
pop
();
if
(
node
==
this
)
{
LERROR
(
"Circle in dependency graph detected. DependencyNode insertion aborted."
);
return
;
}
for
(
std
::
set
<
DependencyNode
*>::
const_iterator
it
=
dependency
->
_dependentNodes
.
begin
();
it
!=
dependency
->
_dependentNodes
.
end
();
++
it
)
{
nodesToVisit
.
push
(
*
it
);
}
}
// add dependency
_dependentNodes
.
insert
(
dependency
);
}
// ================================================================================================
DigraphVisualizationPipeline
::
DigraphVisualizationPipeline
()
:
AutoEvaluationPipeline
()
{
}
DigraphVisualizationPipeline
::~
DigraphVisualizationPipeline
()
{
// delete all DependencyNodes
for
(
std
::
map
<
AbstractProcessor
*
,
DependencyNode
*>::
iterator
it
=
_processorNodeMap
.
begin
();
it
!=
_processorNodeMap
.
end
();
++
it
)
{
delete
it
->
second
;
}
}
void
DigraphVisualizationPipeline
::
addProcessor
(
AbstractProcessor
*
processor
)
{
tgtAssert
(
processor
!=
0
,
"Processor must not be 0!"
);
// add processor to processor list and connect signals
AutoEvaluationPipeline
::
addProcessor
(
processor
);
processor
->
s_invalidated
.
connect
<
DigraphVisualizationPipeline
>
(
this
,
&
DigraphVisualizationPipeline
::
onProcessorInvalidated
);
// create DependencyNode
std
::
map
<
AbstractProcessor
*
,
DependencyNode
*>::
iterator
lb
=
_processorNodeMap
.
lower_bound
(
processor
);
if
(
lb
==
_processorNodeMap
.
end
()
||
lb
->
first
!=
processor
)
{
DependencyNode
*
node
=
new
DependencyNode
(
processor
);
_processorNodeMap
.
insert
(
lb
,
std
::
make_pair
(
processor
,
node
));
}
else
{
LDEBUG
(
"Processor already added!"
);
}
}
void
DigraphVisualizationPipeline
::
addProcessorDependency
(
AbstractProcessor
*
fatherProc
,
AbstractProcessor
*
childProc
)
{
tgtAssert
(
fatherProc
!=
0
,
"Father Processor must not be 0!"
);
tgtAssert
(
childProc
!=
0
,
"Child Processor must not be 0!"
);
// find corresponding DependencyNodes
std
::
map
<
AbstractProcessor
*
,
DependencyNode
*>::
iterator
fatherNode
=
_processorNodeMap
.
find
(
fatherProc
);
std
::
map
<
AbstractProcessor
*
,
DependencyNode
*>::
iterator
childNode
=
_processorNodeMap
.
find
(
childProc
);
if
(
fatherNode
==
_processorNodeMap
.
end
()
||
childNode
==
_processorNodeMap
.
end
())
{
tgtAssert
(
false
,
"Add processors first before defining dependencies between them!"
);
LERROR
(
"Could not find DependencyNodes for at least one of the given processors. No dependency added!"
);
return
;
}
// add dependency
fatherNode
->
second
->
addDependency
(
childNode
->
second
);
}
void
DigraphVisualizationPipeline
::
onProcessorInvalidated
(
AbstractProcessor
*
processor
)
{
// dirty hack - implement proper initialization...
if
(
_canvas
==
0
)
return
;
// TODO: think about a more elaborate implementation, this one doesn't care about the processor graph
std
::
map
<
AbstractProcessor
*
,
DependencyNode
*>::
iterator
node
=
_processorNodeMap
.
find
(
processor
);
if
(
node
!=
_processorNodeMap
.
end
())
{
if
(
node
->
second
->
_isVisualizationProcessor
)
{
GLJobProc
.
enqueueJob
(
_canvas
,
makeJobOnHeap
<
DigraphVisualizationPipeline
,
AbstractProcessor
*
,
bool
>
(
this
,
&
DigraphVisualizationPipeline
::
executeProcessor
,
processor
,
true
),
OpenGLJobProcessor
::
SerialJob
);
}
else
{
SimpleJobProc
.
enqueueJob
(
makeJob
<
DigraphVisualizationPipeline
,
AbstractProcessor
*
,
bool
>
(
this
,
&
DigraphVisualizationPipeline
::
executeProcessor
,
processor
,
false
));
}
}
else
{
LWARNING
(
"Caught invalidation of a processor that is not in the processor graph!"
);
}
}
}
core/pipeline/pipelinefactory.cpp
0 → 100644
View file @
67cb4073
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universität München
// Boltzmannstr. 3, 85748 Garching b. München, Germany
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// The licensing of this softare is not yet resolved. Until then, redistribution in source or
// binary forms outside the CAMP chair is not permitted, unless explicitly stated in legal form.
// However, the names of the original authors and the above copyright notice must retain in its
// original state in any case.
//
// Legal disclaimer provided by the BSD license:
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// ================================================================================================
#include
"pipelinefactory.h"
#include
<sstream>
namespace
campvis
{
// declare one single symbol for the PipelineFactory singleton
tbb
::
atomic
<
PipelineFactory
*>
PipelineFactory
::
_singleton
;
std
::
string
PipelineFactory
::
toString
()
{
std
::
stringstream
ss
;
ss
<<
_pipelineMap
.
size
()
<<
" Pipelines registered: "
;
for
(
std
::
map
<
std
::
string
,
AbstractPipeline
*
(
*
)(
DataContainer
*
)
>::
iterator
it
=
_pipelineMap
.
begin
();
it
!=
_pipelineMap
.
end
();
++
it
)
{
ss
<<
it
->
first
<<
", "
;
}
return
ss
.
str
();
}
}
\ No newline at end of file
core/pipeline/
digraphvisualization
pipeline.h
→
core/pipeline/pipeline
factory
.h
View file @
67cb4073
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universität München
// Boltzmannstr. 3, 85748 Garching b. München, Germany
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// The licensing of this softare is not yet resolved. Until then, redistribution in source or
// binary forms outside the CAMP chair is not permitted, unless explicitly stated in legal form.
// However, the names of the original authors and the above copyright notice must retain in its
// original state in any case.
//
// Legal disclaimer provided by the BSD license:
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// ================================================================================================
#ifndef DIGRAPHVISUALIZATIONPIPELINE_H__
#define DIGRAPHVISUALIZATIONPIPELINE_H__
#include
"sigslot/sigslot.h"
#include
"tgt/vector.h"
#include
"tgt/event/eventlistener.h"
#include
"core/pipeline/autoevaluationpipeline.h"
#include
"core/properties/genericproperty.h"
#include
<map>
#include
<set>
namespace
campvis
{
class
VisualizationProcessor
;
/**
* Specialization of the AutoEvaluationPipeline that performs automatic evaluation based on
* an acyclic directed dependency graph.
*
* \todo Implement thread-safety. The current graph implementation is \b not thread-safe.
*/
class
DigraphVisualizationPipeline
:
public
AutoEvaluationPipeline
{
public:
/**
* Creates a DigraphVisualizationPipeline.
*/
DigraphVisualizationPipeline
();
/**
* Virtual Destructor
**/
virtual
~
DigraphVisualizationPipeline
();
/**
* Execute this pipeline.
* Pipeline must have a valid canvas set before calling this method.
**/
virtual
void
execute
()
=
0
;
/**
* Adds a processor to this pipeline, so that it will be managed.
*
* \note Add each processor only once!
* \param processor Processor to add
*/
void
addProcessor
(
AbstractProcessor
*
processor
);
/**
* Adds a dependency link between two processors.
* The processor \a childProc needs to be executed every time when \a fatherProc has been evaluated.
* \note Add each dependency between two processors only once!
* \param fatherProc The processor \a childProc is dependent on.
* \param childProc The dependent processor of \a fatherProc.
*/
void
addProcessorDependency
(
AbstractProcessor
*
fatherProc
,
AbstractProcessor
*
childProc
);
protected:
/**
* Struct for the nodes defining the processor evaluation dependency graph.
* Each Node represents one processor and stores the processors which are dependent on this
* processors, hence, the ones which need to be updated afterwards.
*
* \todo This struct is \b not thread-safe!
*/
struct
DependencyNode
{
/**
* Creates a new DependencyNode for the given Processor
* \param processor The processor this node represents. Must not be 0.
*/
DependencyNode
(
AbstractProcessor
*
processor
);
/**
* Adds the given DependencyNode as dependency (child) of this node.
* \param dependency DependencyNode containing a processor which needs to be updated after this one.
*/
void
addDependency
(
DependencyNode
*
dependency
);
AbstractProcessor
*
_processor
;
///< Processor this node wraps around
bool
_isVisualizationProcessor
;
///< Flag whether \a _processor is a VisualizationProcessor (hence, needs an OpenGL context)
std
::
set
<
DependencyNode
*>
_dependentNodes
;
///< Set of all dependent nodes.
};
/**
* Slot getting called when one of the observed processors got invalidated.
* The default behaviour is just to set the invalidation level to invalid.
* \param processor The processor that emitted the signal
*/
virtual
void
onProcessorInvalidated
(
AbstractProcessor
*
processor
);
static
const
std
::
string
loggerCat_
;
std
::
map
<
AbstractProcessor
*
,
DependencyNode
*>
_processorNodeMap
;
tbb
::
atomic
<
DependencyNode
*>
_topNodeToEvaluate
;
};
}
#endif // DIGRAPHVISUALIZATIONPIPELINE_H__
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universität München
// Boltzmannstr. 3, 85748 Garching b. München, Germany
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// The licensing of this softare is not yet resolved. Until then, redistribution in source or
// binary forms outside the CAMP chair is not permitted, unless explicitly stated in legal form.
// However, the names of the original authors and the above copyright notice must retain in its
// original state in any case.
//
// Legal disclaimer provided by the BSD license:
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// ================================================================================================
#ifndef PIPELINEFACTORY_H__
#define PIPELINEFACTORY_H__
#include
"tgt/logmanager.h"
#include
"tgt/singleton.h"