tumvisapplication.cpp 9.83 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
#include "core/tools/opengljobprocessor.h"
46
47
48
49
50
51
#include "core/pipeline/abstractpipeline.h"
#include "core/pipeline/visualizationpipeline.h"
#include "core/pipeline/pipelineevaluator.h"

namespace TUMVis {

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

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

66
67
        _mainWindow = new MainWindow(this);
        tgt::QtContextManager::init();
68
69

        OpenGLJobProcessor::init();
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
95
96
97
    }

    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");
98
99
100

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

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

105
106
107
108
109
110
111
112
        // 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.");
        }

113
114
115
116
        if (_useOpenCL) {
            kisscl::CLRuntime::init();
        }

117
118
        if (_argc > 0) {
            // ugly hack
schultezub's avatar
schultezub committed
119
120
121
122
123
124
125
126
127
            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");
            }
128
129
130
131
132
133
134
135
136
137
138
139
        }

        // 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();
        }

140
        GLJobProc.start();
141
142
143
144
145
146
        _initialized = true;
    }

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

147
148
        GLJobProc.stop();

149
150
151
        {
            // Deinit everything OpenGL related using the local context.
            tgt::GLContextScopedLock lock(_localContext->getContext());
152

153
154
155
156
157
158
159
160
161
162
163
164
            // 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();
165
166
167
168

            if (_useOpenCL) {
                kisscl::CLRuntime::deinit();
            }
169
170
        }

171
172
        OpenGLJobProcessor::deinit();

173
174
175
        tgt::QtContextManager::deinit();
        tgt::deinit();

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

179
180
181
182
183
184
185
186
187
        _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();

188
189
        _mainWindow->show();

190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
        // 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) {
213
        tgtAssert(_initialized == false, "Adding pipelines after initialization is currently not supported.");
214
215
216
217
218
        tgtAssert(pipeline != 0, "Pipeline must not be 0.");
        _pipelines.push_back(pipeline);

        PipelineEvaluator* pe = new PipelineEvaluator(pipeline);
        _pipelineEvaluators.push_back(pe);
219
220

        s_PipelinesChanged();
221
222
223
    }

    void TumVisApplication::addVisualizationPipeline(const std::string& name, VisualizationPipeline* vp) {
224
        tgtAssert(_initialized == false, "Adding pipelines after initialization is currently not supported.");
225
226
227
228
229
230
231
232
233
234
235
        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));
236
237
238
239
240

        // 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);
241
242
243
    }

}