2.12.2021, 9:00 - 11:00: Due to updates GitLab may be unavailable for some minutes between 09:00 and 11:00.

abstractpipeline.cpp 10.4 KB
Newer Older
1

2
3
// ================================================================================================
// 
schultezub's avatar
schultezub committed
4
// This file is part of the CAMPVis Software Framework.
5
// 
6
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
schultezub's avatar
schultezub committed
7
//      Christian Schulte zu Berge <christian.szb@in.tum.de>
8
//      Chair for Computer Aided Medical Procedures
9
10
//      Technische Universitaet Muenchen
//      Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
11
// 
schultezub's avatar
schultezub committed
12
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
13
// 
14
15
16
17
// 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
18
// 
19
20
21
22
// 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.
23
24
25
// 
// ================================================================================================

26
#include "abstractpipeline.h"
schultezub's avatar
schultezub committed
27

28
29
#include <tbb/tick_count.h>

schultezub's avatar
schultezub committed
30
#include "tgt/exception.h"
31
#include "tgt/glcanvas.h"
32
33
#include "tgt/glcontextmanager.h"
#include "tgt/painter.h"
34
35
36
#include "tgt/tgt_gl.h"

#include "core/pipeline/visualizationprocessor.h"
37
#include "core/pipeline/abstractprocessor.h"
38

39

schultezub's avatar
schultezub committed
40
41
namespace campvis {
    const std::string AbstractPipeline::loggerCat_ = "CAMPVis.core.datastructures.AbstractPipeline";
42

43
    AbstractPipeline::AbstractPipeline(DataContainer* dc) 
44
        : HasPropertyCollection()
45
46
        , tgt::EventHandler()
        , tgt::EventListener()
47
        , _data(dc)
48
49
50
51
        , _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)
schultezub's avatar
   
schultezub committed
52
    {
53
54
        tgtAssert(_data != 0, "Pointer to the DataContainer for this pipeline must not be 0!");

55
        _enabled = false;
56
        _pipelineDirty = true;
57

58
59
        addProperty(_renderTargetID);
        addProperty(_canvasSize);
schultezub's avatar
   
schultezub committed
60
61
62
    }

    AbstractPipeline::~AbstractPipeline() {
63

schultezub's avatar
   
schultezub committed
64
65
    }

66
    void AbstractPipeline::init() {
67
68
        _renderTargetID.s_changed.connect<AbstractPipeline>(this, &AbstractPipeline::onPropertyChanged);

schultezub's avatar
schultezub committed
69
70
        initAllProperties();

71
        // initialize all processors:
schultezub's avatar
schultezub committed
72
73
74
75
76
77
78
79
        for (std::vector<AbstractProcessor*>::iterator it = _processors.begin(); it != _processors.end(); ++it) {
            try {
                (*it)->init();
            }
            catch (tgt::Exception& e) {
                LERROR("Caught Exception during initialization of processor: " << e.what());
            }
        }
80
    }
schultezub's avatar
schultezub committed
81

82
    void AbstractPipeline::deinit() {
schultezub's avatar
schultezub committed
83
84
        deinitAllProperties();

85
86
87
        // deinitialize all processors:
        for (std::vector<AbstractProcessor*>::iterator it = _processors.begin(); it != _processors.end(); ++it) {
            try {
schultezub's avatar
schultezub committed
88
                (*it)->s_invalidated.disconnect(this);
89
90
91
92
93
94
                (*it)->deinit();
            }
            catch (tgt::Exception& e) {
                LERROR("Caught Exception during deinitialization of processor: " << e.what());
            }
        }
95

96
97
        _renderTargetID.s_changed.disconnect(this);

98
        // clear DataContainer
99
        _data->clear();
100
101
    }

102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
    void AbstractPipeline::run() {
        std::unique_lock<std::mutex> lock(*tgt::GlContextManager::getRef().getGlMutexForContext(_canvas));
        tgt::GlContextManager::getRef().acquireContext(_canvas, false);

        while (! _stopExecution) {
            if (_enabled && _pipelineDirty) {
                // mark pipeline as not dirty
                _pipelineDirty = false;

                // execute pipeline
                executePipeline();

                // paint on canvas
                _canvas->getPainter()->paint();
            }

118
            if (!_stopExecution && (!_enabled || !_pipelineDirty)) {
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
                tgt::GlContextManager::getRef().releaseContext(_canvas, false);
                _evaluationCondition.wait(lock);
                tgt::GlContextManager::getRef().acquireContext(_canvas, false);
            }
        }

        tgt::GlContextManager::getRef().releaseContext(_canvas, false);
    }

    void AbstractPipeline::stop() {
        _stopExecution = true;
        _evaluationCondition.notify_all();

        Runnable::stop();
    }

schultezub's avatar
schultezub committed
135
    void AbstractPipeline::onPropertyChanged(const AbstractProperty* prop) {
136
        if (prop == &_renderTargetID) {
137
            setPipelineDirty();
138
        }
139
        else if (prop == &_canvasSize && _canvas != nullptr && !_ignoreCanvasSizeUpdate) {
140
141
142
143
144
145
            if (_canvasSize.getValue() != _canvas->getSize()) {
                _ignoreCanvasSizeUpdate = true;
                _canvas->setSize(_canvasSize.getValue());
                _ignoreCanvasSizeUpdate = false;
            }
        }
schultezub's avatar
schultezub committed
146
147
148
    }

    const DataContainer& AbstractPipeline::getDataContainer() const {
149
        return *_data;
schultezub's avatar
schultezub committed
150
151
    }

152
    DataContainer& AbstractPipeline::getDataContainer() {
153
        return *_data;
154
155
    }

156
    void AbstractPipeline::executeProcessor(AbstractProcessor* processor) {
157
158
        tgtAssert(processor != 0, "Processor must not be 0.");

159
        // execute processor if needed
160
        if (processor->getEnabled() && !processor->isLocked()) {
161
            if (! processor->isValid()) {
162
163
164
                tbb::tick_count startTime;
                if (processor->getClockExecutionTime())
                    startTime = tbb::tick_count::now();
165
166

                try {
167
                    processor->process(*_data);
168
169
170
171
172
173
174
175
176
                }
                catch (std::exception& e) {
                    LERROR("Caught unhandled exception while executing processor " << processor->getName() << ": " << e.what());
                }
                catch (...) {
                    LERROR("Caught unhandled exception while executing processor " << processor->getName() << ": unknown exception");
                }

                if (processor->getClockExecutionTime()) {
177
178
                    tbb::tick_count endTime = tbb::tick_count::now();
                    LINFO("Executed processor " << processor->getName() << " duration: " << (endTime - startTime).seconds());
179
                }
180
            }
181
        }
182
183
    }

184
185
186
187
    void AbstractPipeline::executeProcessorAndCheckOpenGLState(AbstractProcessor* processor) {
        AbstractPipeline::executeProcessor(processor);

#ifdef CAMPVIS_DEBUG
188
189
        tgtAssert(tgt::getGlBool(GL_DEPTH_TEST) == false, "Invalid OpenGL state after processor execution, GL_DEPTH_TEST != false.");
        tgtAssert(tgt::getGlBool(GL_SCISSOR_TEST) == false, "Invalid OpenGL state after processor execution, GL_SCISSOR_TEST != false.");
190

191
192
        tgtAssert(tgt::getGlInt(GL_CULL_FACE_MODE) == GL_BACK, "Invalid OpenGL state after processor execution, GL_CULL_FACE_MODE != GL_BACk.");
        tgtAssert(tgt::getGlInt(GL_DEPTH_FUNC) == GL_LESS, "Invalid OpenGL state after processor execution, GL_DEPTH_FUNC != GL_LESS.");
193

194
        tgtAssert(tgt::getGlFloat(GL_DEPTH_CLEAR_VALUE) == 1.f, "Invalid OpenGL state after processor execution, GL_DEPTH_CLEAR_VALUE != 1.f.");
195

196
197
198
199
        tgtAssert(tgt::getGlFloat(GL_RED_SCALE) == 1.f, "Invalid OpenGL state after processor execution, GL_RED_SCALE != 1.f.");
        tgtAssert(tgt::getGlFloat(GL_GREEN_SCALE) == 1.f, "Invalid OpenGL state after processor execution, GL_GREEN_SCALE != 1.f.");
        tgtAssert(tgt::getGlFloat(GL_BLUE_SCALE) == 1.f, "Invalid OpenGL state after processor execution, GL_BLUE_SCALE != 1.f.");
        tgtAssert(tgt::getGlFloat(GL_ALPHA_SCALE) == 1.f, "Invalid OpenGL state after processor execution, GL_ALPHA_SCALE != 1.f.");
200

201
202
203
204
        tgtAssert(tgt::getGlFloat(GL_RED_BIAS) == 0.f, "Invalid OpenGL state after processor execution, GL_RED_BIAS != 0.f.");
        tgtAssert(tgt::getGlFloat(GL_GREEN_BIAS) == 0.f, "Invalid OpenGL state after processor execution, GL_GREEN_BIAS != 0.f.");
        tgtAssert(tgt::getGlFloat(GL_BLUE_BIAS) == 0.f, "Invalid OpenGL state after processor execution, GL_BLUE_BIAS != 0.f.");
        tgtAssert(tgt::getGlFloat(GL_ALPHA_BIAS) == 0.f, "Invalid OpenGL state after processor execution, GL_ALPHA_BIAS != 0.f.");
205
206
207
#endif
    }

208
209
210
211
    const std::vector<AbstractProcessor*>& AbstractPipeline::getProcessors() const {
        return _processors;
    }

212
213
214
215
216
217
    bool AbstractPipeline::getEnabled() const {
        return _enabled;
    }

    void AbstractPipeline::setEnabled(bool enabled) {
        _enabled = enabled;
218
        setPipelineDirty();
219
220
    }

221
222
223
    void AbstractPipeline::onEvent(tgt::Event* e) {
        // copy and paste from tgt::EventHandler::onEvent() but without deleting e
        for (size_t i = 0 ; i < listeners_.size() ; ++i) {
Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
224
225
226
227
            // don't forward this event to ourselves - otherwise we'll end up with an endless loop.
            if (listeners_[i] == this) {
                tgt::EventListener::onEvent(e);
            }
228
            // check if current listener listens to the eventType of e
Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
229
            else if (listeners_[i]->getEventTypes() & e->getEventType() ){
230
231
                listeners_[i]->onEvent(e);
            }
Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
232
233
234

            if (e->isAccepted())
                break;
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
        }
    }

    void AbstractPipeline::setCanvas(tgt::GLCanvas* canvas) {
        _canvas = canvas;
    }

    void AbstractPipeline::setRenderTargetSize(const tgt::ivec2& size) {
        if (_canvasSize.getValue() != size && !_ignoreCanvasSizeUpdate) {
            _canvasSize.setValue(size);
        }
    }

    const tgt::ivec2& AbstractPipeline::getRenderTargetSize() const {
        return _canvasSize.getValue();
    }

    const std::string& AbstractPipeline::getRenderTargetID() const {
        return _renderTargetID.getValue();
    }

256
    void AbstractPipeline::addProcessor(AbstractProcessor* processor) {
schultezub's avatar
schultezub committed
257
        tgtAssert(processor != 0, "Processor must not be 0.")
258
259
        _processors.push_back(processor);
    }
260

261
262
    void AbstractPipeline::setPipelineDirty() {
        _pipelineDirty = true;
263

264
265
        if (_enabled)
            _evaluationCondition.notify_all();
266
    }
267
}