campvisapplication.cpp 9.38 KB
Newer Older
1
2
// ================================================================================================
// 
schultezub's avatar
schultezub committed
3
// This file is part of the CAMPVis Visualization Framework.
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
// 
// 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.
// 
// ================================================================================================

schultezub's avatar
schultezub committed
29
#include "campvisapplication.h"
30
31
32
33

#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"

schultezub's avatar
schultezub committed
43
#include "application/campvispainter.h"
44
#include "application/gui/mainwindow.h"
45
#include "core/tools/opengljobprocessor.h"
46
#include "core/tools/quadrenderer.h"
47
48
49
50
#include "core/pipeline/abstractpipeline.h"
#include "core/pipeline/visualizationpipeline.h"
#include "core/pipeline/pipelineevaluator.h"

schultezub's avatar
schultezub committed
51
namespace campvis {
52

53
    const std::string CampVisApplication::loggerCat_ = "CAMPVis.application.CampVisApplication";
54

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

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

        OpenGLJobProcessor::init();
71
72
    }

73
74
    CampVisApplication::~CampVisApplication() {
        tgtAssert(_initialized == false, "Destructing initialized CampVisApplication, deinitialize first!");
75
76
77
78
79
80
81
82
83
84
85
86
87

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

88
89
    void CampVisApplication::init() {
        tgtAssert(_initialized == false, "Tried to initialize CampVisApplication twice.");
90
91
92
93
94
95
96
97
98

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

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

102
103
104
        tgt::initGL(featureset);
        LGL_ERROR;

105
        // ensure matching OpenGL specs
106
        if (GpuCaps.getGlVersion() < tgt::GpuCapabilities::GlVersion::TGT_GL_VERSION_3_3) {
schultezub's avatar
schultezub committed
107
            LERROR("Your system does not support OpenGL 3.3, which is mandatory. CAMPVis will probably not work as intendet.");
108
        }
109
        if (GpuCaps.getShaderVersion() < tgt::GpuCapabilities::GlVersion::SHADER_VERSION_330) {
schultezub's avatar
schultezub committed
110
            LERROR("Your system does not support GLSL Shader Version 3.30, which is mandatory. CAMPVis will probably not work as intendet.");
111
112
        }

113
114
        QuadRenderer::init();

115
116
117
118
        if (_useOpenCL) {
            kisscl::CLRuntime::init();
        }

119
120
        if (_argc > 0) {
            // ugly hack
schultezub's avatar
schultezub committed
121
122
123
124
125
126
127
128
129
            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");
            }
130
131
        }

132
133
        _mainWindow->init();

134
135
136
137
138
139
140
141
142
143
        // 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();
        }

144
        GLJobProc.start();
145
146
147
        _initialized = true;
    }

148
149
    void CampVisApplication::deinit() {
        tgtAssert(_initialized, "Tried to deinitialize uninitialized CampVisApplication.");
150

151
152
        GLJobProc.stop();

153
154
155
        {
            // Deinit everything OpenGL related using the local context.
            tgt::GLContextScopedLock lock(_localContext->getContext());
156

157
158
159
160
161
162
163
164
165
166
            // 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();
            }

167
168
            _mainWindow->deinit();

169
170
            // deinit OpenGL and tgt
            tgt::deinitGL();
171

172
173
            QuadRenderer::deinit();

174
175
176
            if (_useOpenCL) {
                kisscl::CLRuntime::deinit();
            }
177
178
        }

179
180
        OpenGLJobProcessor::deinit();

181
182
183
        tgt::QtContextManager::deinit();
        tgt::deinit();

184
        // MainWindow dtor needs a valid CampVisApplication, so we need to call it here instead of during destruction.
schultezub's avatar
schultezub committed
185
186
        delete _mainWindow;

187
188
189
        _initialized = false;
    }

190
191
    int CampVisApplication::run() {
        tgtAssert(_initialized, "Tried to run uninitialized CampVisApplication.");
192
193
194
195

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

196
197
        _mainWindow->show();

198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
        // Start evaluator/render threads
        for (std::vector<PipelineEvaluator*>::iterator it = _pipelineEvaluators.begin(); it != _pipelineEvaluators.end(); ++it) {
            (*it)->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();
        }

        return toReturn;
    }

214
    void CampVisApplication::addPipeline(AbstractPipeline* pipeline) {
215
        tgtAssert(_initialized == false, "Adding pipelines after initialization is currently not supported.");
216
217
218
219
220
        tgtAssert(pipeline != 0, "Pipeline must not be 0.");
        _pipelines.push_back(pipeline);

        PipelineEvaluator* pe = new PipelineEvaluator(pipeline);
        _pipelineEvaluators.push_back(pe);
221
222

        s_PipelinesChanged();
223
224
    }

225
    void CampVisApplication::addVisualizationPipeline(const std::string& name, VisualizationPipeline* vp) {
226
        tgtAssert(_initialized == false, "Adding pipelines after initialization is currently not supported.");
227
228
229
        tgtAssert(vp != 0, "Pipeline must not be 0.");

        // create canvas and painter for the VisPipeline and connect all together
schultezub's avatar
schultezub committed
230
        tgt::QtThreadedCanvas* canvas = CtxtMgr.createContext(name, "CAMPVis", tgt::ivec2(512, 512));
231
        GLJobProc.registerContext(canvas);
232
233
234
235
236
237
        canvas->init();

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

        _visualizations.push_back(std::make_pair(vp, painter));
238

239
        vp->setCanvas(canvas);
240
        addPipeline(vp);
241
242

        CtxtMgr.releaseCurrentContext();
243
244
245
    }

}