tumvisapplication.cpp 9.65 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// ================================================================================================
// 
// This file is part of the TUMVis Visualization 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
// 
// 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.
// 
// ================================================================================================

29
30
31
32
33
#include "tumvisapplication.h"

#include "tgt/assert.h"
#include "tgt/exception.h"
#include "tgt/glcontext.h"
34
#include "tgt/gpucapabilities.h"
35
36
37
38
39
40
#include "tgt/shadermanager.h"
#include "tgt/qt/qtapplication.h"
#include "tgt/qt/qtthreadedcanvas.h"
#include "tgt/qt/qtcontextmanager.h"
#include "tbb/include/tbb/compat/thread"

41
42
#include "kisscl/clruntime.h"

43
#include "application/tumvispainter.h"
44
#include "application/gui/mainwindow.h"
45
46
47
48
49
50
#include "core/pipeline/abstractpipeline.h"
#include "core/pipeline/visualizationpipeline.h"
#include "core/pipeline/pipelineevaluator.h"

namespace TUMVis {

51
52
    const std::string TumVisApplication::loggerCat_ = "TUMVis.application.TumVisApplication";

53
    TumVisApplication::TumVisApplication(int argc, char** argv, bool useOpenCL) 
54
55
        : QApplication(argc, argv)
        , _localContext(0)
56
        , _mainWindow(0)
57
        , _initialized(false)
58
        , _useOpenCL(useOpenCL)
59
60
61
        , _argc(argc)
        , _argv(argv)
    {
62
63
        // Make Xlib and GLX thread safe under X11
        QApplication::setAttribute(Qt::AA_X11InitThreads);
64

65
66
        _mainWindow = new MainWindow(this);
        tgt::QtContextManager::init();
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
    }

    TumVisApplication::~TumVisApplication() {
        tgtAssert(_initialized == false, "Destructing initialized TumVisApplication, deinitialize first!");

        // delete everything in the right order:
        for (std::vector<PipelineEvaluator*>::iterator it = _pipelineEvaluators.begin(); it != _pipelineEvaluators.end(); ++it) {
            delete *it;
        }
        for (std::vector< std::pair<VisualizationPipeline*, TumVisPainter*> >::iterator it = _visualizations.begin(); it != _visualizations.end(); ++it) {
            delete it->second;
        }
        for (std::vector<AbstractPipeline*>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
            delete *it;
        }
    }

    void TumVisApplication::init() {
        tgtAssert(_initialized == false, "Tried to initialize TumVisApplication twice.");

        // Init TGT
        tgt::InitFeature::Features featureset = tgt::InitFeature::ALL;
        tgt::init(featureset);
        LogMgr.getConsoleLog()->addCat("", true);

        // create a local OpenGL context and init GL
        _localContext = CtxtMgr.createContext("AppContext", "", tgt::ivec2(16, 16));
        tgtAssert(_localContext != 0, "Could not create local OpenGL context");
95
96
97

        tgt::GLContextScopedLock lock(_localContext->getContext());

98
        tgt::initGL(featureset);
schultezub's avatar
schultezub committed
99
        //ShdrMgr.setGlobalHeader("#version 130\n");
100
101
        LGL_ERROR;

102
103
104
105
106
107
108
109
        // ensure matching OpenGL specs
        if (GpuCaps.getGlVersion() < tgt::GpuCapabilities::GlVersion::TGT_GL_VERSION_3_0) {
            LERROR("Your system does not support OpenGL 3.0, which is mandatory. TUMVis will probably not work as intendet.");
        }
        if (GpuCaps.getShaderVersion() < tgt::GpuCapabilities::GlVersion::SHADER_VERSION_130) {
            LERROR("Your system does not support GLSL Shader Version 1.30, which is mandatory. TUMVis will probably not work as intendet.");
        }

110
111
112
113
        if (_useOpenCL) {
            kisscl::CLRuntime::init();
        }

114
115
        if (_argc > 0) {
            // ugly hack
schultezub's avatar
schultezub committed
116
117
118
119
120
121
122
123
124
            std::string basePath(_argv[0]);
            basePath = tgt::FileSystem::parentDir(tgt::FileSystem::parentDir(tgt::FileSystem::parentDir(basePath)));
            ShdrMgr.addPath(basePath);
            ShdrMgr.addPath(basePath + "/core/glsl");

            if (_useOpenCL) {
                CLRtm.addPath(basePath);
                CLRtm.addPath(basePath + "/core/cl");
            }
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
        }

        // init pipeline first
        for (std::vector<AbstractPipeline*>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
            (*it)->init();
        }

        // Now init painters:
        for (std::vector< std::pair<VisualizationPipeline*, TumVisPainter*> >::iterator it = _visualizations.begin(); it != _visualizations.end(); ++it) {
            it->second->init();
        }

        _initialized = true;
    }

    void TumVisApplication::deinit() {
        tgtAssert(_initialized, "Tried to deinitialize uninitialized TumVisApplication.");

143
144
145
        {
            // Deinit everything OpenGL related using the local context.
            tgt::GLContextScopedLock lock(_localContext->getContext());
146

147
148
149
150
151
152
153
154
155
156
157
158
            // Deinit pipeline first
            for (std::vector<AbstractPipeline*>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
                (*it)->deinit();
            }

            // Now deinit painters:
            for (std::vector< std::pair<VisualizationPipeline*, TumVisPainter*> >::iterator it = _visualizations.begin(); it != _visualizations.end(); ++it) {
                it->second->deinit();
            }

            // deinit OpenGL and tgt
            tgt::deinitGL();
159
160
161
162

            if (_useOpenCL) {
                kisscl::CLRuntime::deinit();
            }
163
164
165
166
167
        }

        tgt::QtContextManager::deinit();
        tgt::deinit();

168
        // MainWindow dtor needs a valid TumVisApplication, so we need to call it here instead of during destruction.
schultezub's avatar
schultezub committed
169
170
        delete _mainWindow;

171
172
173
174
175
176
177
178
179
        _initialized = false;
    }

    int TumVisApplication::run() {
        tgtAssert(_initialized, "Tried to run uninitialized TumVisApplication.");

        // disconnect OpenGL context from this thread so that the other threads can acquire an OpenGL context.
        CtxtMgr.releaseCurrentContext();

180
181
        _mainWindow->show();

182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
        // Start evaluator/render threads
        for (std::vector<PipelineEvaluator*>::iterator it = _pipelineEvaluators.begin(); it != _pipelineEvaluators.end(); ++it) {
            (*it)->start();
        }
        for (std::vector< std::pair<VisualizationPipeline*, TumVisPainter*> >::iterator it = _visualizations.begin(); it != _visualizations.end(); ++it) {
            it->second->start();
        }

        // Start QApplication
        int toReturn = QApplication::exec();

        // QApplication has returned -> Stop evaluator/render threads
        for (std::vector<PipelineEvaluator*>::iterator it = _pipelineEvaluators.begin(); it != _pipelineEvaluators.end(); ++it) {
            (*it)->stop();
        }
        for (std::vector< std::pair<VisualizationPipeline*, TumVisPainter*> >::iterator it = _visualizations.begin(); it != _visualizations.end(); ++it) {
            it->second->stop();
        }

        return toReturn;
    }

    void TumVisApplication::addPipeline(AbstractPipeline* pipeline) {
205
        tgtAssert(_initialized == false, "Adding pipelines after initialization is currently not supported.");
206
207
208
209
210
        tgtAssert(pipeline != 0, "Pipeline must not be 0.");
        _pipelines.push_back(pipeline);

        PipelineEvaluator* pe = new PipelineEvaluator(pipeline);
        _pipelineEvaluators.push_back(pe);
211
212

        s_PipelinesChanged();
213
214
215
    }

    void TumVisApplication::addVisualizationPipeline(const std::string& name, VisualizationPipeline* vp) {
216
        tgtAssert(_initialized == false, "Adding pipelines after initialization is currently not supported.");
217
218
219
220
221
222
223
224
225
226
227
        tgtAssert(vp != 0, "Pipeline must not be 0.");

        // create canvas and painter for the VisPipeline and connect all together
        tgt::QtThreadedCanvas* canvas = CtxtMgr.createContext(name, "TUMVis", tgt::ivec2(512, 512));
        canvas->init();

        TumVisPainter* painter = new TumVisPainter(canvas, vp);
        canvas->setPainter(painter, false);
        CtxtMgr.releaseCurrentContext();

        _visualizations.push_back(std::make_pair(vp, painter));
228
229
230
231
232

        // TODO: is there a more leightweight method to create a context for the pipeline (just performing off-screen rendering)?
        tgt::QtThreadedCanvas* evaluationContext = CtxtMgr.createContext(name + "_eval", "", tgt::ivec2(512, 512));
        vp->setCanvas(evaluationContext);
        addPipeline(vp);
233
234
235
    }

}