Currently job artifacts in CI/CD pipelines on LRZ GitLab never expire. Starting from Wed 26.1.2022 the default expiration time will be 30 days (GitLab default). Currently existing artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

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

schultezub's avatar
schultezub committed
25
#include "campvisapplication.h"
26
27
28

#include "tgt/assert.h"
#include "tgt/exception.h"
29
#include "tgt/glcanvas.h"
30
#include "tgt/gpucapabilities.h"
31
32
33
34
#include "tgt/shadermanager.h"
#include "tgt/qt/qtapplication.h"
#include "tgt/qt/qtthreadedcanvas.h"
#include "tgt/qt/qtcontextmanager.h"
schultezub's avatar
schultezub committed
35
#include "tbb/compat/thread"
36

schultezub's avatar
schultezub committed
37
#ifdef HAS_KISSCL
38
#include "kisscl/clruntime.h"
schultezub's avatar
schultezub committed
39
#endif
40

schultezub's avatar
schultezub committed
41
#include "application/campvispainter.h"
42
#include "application/gui/mainwindow.h"
43
#include "core/tools/opengljobprocessor.h"
44
#include "core/tools/simplejobprocessor.h"
45
#include "core/tools/stringutils.h"
46
#include "core/tools/quadrenderer.h"
47
#include "core/pipeline/abstractpipeline.h"
48
#include "modules/pipelinefactory.h"
49

schultezub's avatar
schultezub committed
50
namespace campvis {
51

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

54
    CampVisApplication::CampVisApplication(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
        SimpleJobProcessor::init();
71
72
    }

73
74
    CampVisApplication::~CampVisApplication() {
        tgtAssert(_initialized == false, "Destructing initialized CampVisApplication, deinitialize first!");
75
76

        // delete everything in the right order:
77
        for (std::vector< std::pair<AbstractPipeline*, CampVisPainter*> >::iterator it = _visualizations.begin(); it != _visualizations.end(); ++it) {
78
79
80
81
82
            delete it->second;
        }
        for (std::vector<AbstractPipeline*>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
            delete *it;
        }
83
84
85
        for (std::vector<DataContainer*>::iterator it = _dataContainers.begin(); it != _dataContainers.end(); ++it) {
            delete *it;
        }
86
87
    }

88
89
    void CampVisApplication::init() {
        tgtAssert(_initialized == false, "Tried to initialize CampVisApplication twice.");
90

91
92
93
        // parse argument list and create pipelines
        QStringList pipelinesToAdd = this->arguments();
        for (int i = 1; i < pipelinesToAdd.size(); ++i) {
94
95
            DataContainer* dc = createAndAddDataContainer("DataContainer #" + StringUtils::toString(_dataContainers.size() + 1));
            AbstractPipeline* p = PipelineFactory::getRef().createPipeline(pipelinesToAdd[i].toStdString(), dc);
96
97
98
99
            if (p != 0)
                addPipeline(pipelinesToAdd[i].toStdString(), p);
        }

100
101
102
103
104
105
        // Init TGT
        tgt::InitFeature::Features featureset = tgt::InitFeature::ALL;
        tgt::init(featureset);
        LogMgr.getConsoleLog()->addCat("", true);

        // create a local OpenGL context and init GL
106
        _localContext = tgt::GlContextManager::getRef().createContext("AppContext", "", tgt::ivec2(16, 16));
107
        tgtAssert(_localContext != 0, "Could not create local OpenGL context");
108

109
        tgt::GLContextScopedLock lock(_localContext);
110

111
        tgt::initGL(featureset);
112
        ShdrMgr.setGlobalHeader("#version 330\n");
113
114
        LGL_ERROR;

115
        // ensure matching OpenGL specs
116
        if (GpuCaps.getGlVersion() < tgt::GpuCapabilities::GlVersion::TGT_GL_VERSION_3_3) {
117
            LERROR("Your system does not support OpenGL 3.3, which is mandatory. CAMPVis will probably not work as intended.");
118
        }
119
        if (GpuCaps.getShaderVersion() < tgt::GpuCapabilities::GlVersion::SHADER_VERSION_330) {
120
121
122
123
            LERROR("Your system does not support GLSL Shader Version 3.30, which is mandatory. CAMPVis will probably not work as intended.");
        }
        if (!GpuCaps.isNpotSupported() && !GpuCaps.areTextureRectanglesSupported()) {
            LERROR("Neither non-power-of-two textures nor texture rectangles seem to be supported. CAMPVis will probably not work as intended.");
124
125
        }

126
127
        QuadRenderer::init();

schultezub's avatar
schultezub committed
128
#ifdef HAS_KISSCL
129
130
131
        if (_useOpenCL) {
            kisscl::CLRuntime::init();
        }
schultezub's avatar
schultezub committed
132
#endif
133

134
135
        if (_argc > 0) {
            // ugly hack
schultezub's avatar
schultezub committed
136
            std::string basePath(_argv[0]);
137
138
139
140
141
            basePath = tgt::FileSystem::parentDir(basePath);
            ShdrMgr.addPath(basePath);
            ShdrMgr.addPath(basePath + "/core/glsl");

            basePath = tgt::FileSystem::parentDir(tgt::FileSystem::parentDir(basePath));
schultezub's avatar
schultezub committed
142
143
144
            ShdrMgr.addPath(basePath);
            ShdrMgr.addPath(basePath + "/core/glsl");

145
146
147
148
149
150
151
152
#ifdef CAMPVIS_SOURCE_DIR
            {
                std::string sourcePath = CAMPVIS_SOURCE_DIR;
                ShdrMgr.addPath(sourcePath);
                ShdrMgr.addPath(sourcePath + "/core/glsl");
            }
#endif

schultezub's avatar
schultezub committed
153
#ifdef HAS_KISSCL
schultezub's avatar
schultezub committed
154
155
156
157
            if (_useOpenCL) {
                CLRtm.addPath(basePath);
                CLRtm.addPath(basePath + "/core/cl");
            }
158
159
160
161
162
163
164
165
166

#ifdef CAMPVIS_SOURCE_DIR
            {
                std::string sourcePath = CAMPVIS_SOURCE_DIR;
                CLRtm.addPath(sourcePath);
                CLRtm.addPath(sourcePath + "/core/glsl");
            }
#endif

schultezub's avatar
schultezub committed
167
#endif
168
169
        }

170
171
        _mainWindow->init();

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

        // Now init painters:
178
        for (std::vector< std::pair<AbstractPipeline*, CampVisPainter*> >::iterator it = _visualizations.begin(); it != _visualizations.end(); ++it) {
179
180
181
            it->second->init();
        }

182
        GLJobProc.start();
183
184
185
        _initialized = true;
    }

186
187
    void CampVisApplication::deinit() {
        tgtAssert(_initialized, "Tried to deinitialize uninitialized CampVisApplication.");
188

189
190
        GLJobProc.stop();

191
192
        {
            // Deinit everything OpenGL related using the local context.
193
            tgt::GLContextScopedLock lock(_localContext);
194

195
196
197
198
199
200
            // Deinit pipeline first
            for (std::vector<AbstractPipeline*>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
                (*it)->deinit();
            }

            // Now deinit painters:
201
            for (std::vector< std::pair<AbstractPipeline*, CampVisPainter*> >::iterator it = _visualizations.begin(); it != _visualizations.end(); ++it) {
202
203
204
                it->second->deinit();
            }

205
206
            _mainWindow->deinit();

207
208
            QuadRenderer::deinit();

schultezub's avatar
schultezub committed
209
#ifdef HAS_KISSCL
210
211
212
            if (_useOpenCL) {
                kisscl::CLRuntime::deinit();
            }
schultezub's avatar
schultezub committed
213
#endif
214
215
216
217


            // deinit OpenGL and tgt
            tgt::deinitGL();
218
219
        }

220
        SimpleJobProcessor::deinit();
221
        OpenGLJobProcessor::deinit();
222
        PipelineFactory::deinit();
223

224
225
226
        tgt::QtContextManager::deinit();
        tgt::deinit();

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

230
231
232
        _initialized = false;
    }

233
234
    int CampVisApplication::run() {
        tgtAssert(_initialized, "Tried to run uninitialized CampVisApplication.");
235
236

        // disconnect OpenGL context from this thread so that the other threads can acquire an OpenGL context.
237
        tgt::GlContextManager::getRef().releaseCurrentContext();
238

239
240
        _mainWindow->show();

241
242
243
244
245
246
        // Start QApplication
        int toReturn = QApplication::exec();

        return toReturn;
    }

247
    void CampVisApplication::addPipeline(const std::string& name, AbstractPipeline* pipeline) {
248
249
        tgtAssert(pipeline != 0, "Pipeline must not be 0.");

250
251
252
253
        // if CAMPVis is already fully initialized, we need to temporarily shut down its
        // OpenGL job processor, since we need to create a new context.
        if (_initialized) {
            GLJobProc.pause();
254
            {
255
256
257
                tgt::QtThreadedCanvas* canvas = dynamic_cast<tgt::QtThreadedCanvas*>(tgt::GlContextManager::getRef().createContext(name, "CAMPVis", tgt::ivec2(512, 512)));
                tgtAssert(canvas != 0, "Dynamic cast failed. This should not be the case, since we initialized the GlContextManager singleton with a QtContextManager.");
                tgt::GLContextScopedLock lock(canvas);
258
259
260
                addPipelineImpl(canvas, name, pipeline);
            }
            GLJobProc.resume();
261
        }
262
        else {
263
264
            tgt::QtThreadedCanvas* canvas = dynamic_cast<tgt::QtThreadedCanvas*>(tgt::GlContextManager::getRef().createContext(name, "CAMPVis", tgt::ivec2(512, 512)));
            tgtAssert(canvas != 0, "Dynamic cast failed. This should not be the case, since we initialized the GlContextManager singleton with a QtContextManager.");
265
266
267
268
269
            addPipelineImpl(canvas, name, pipeline);
        }

        s_PipelinesChanged();
    }
270

271
    void CampVisApplication::addPipelineImpl(tgt::QtThreadedCanvas* canvas, const std::string& name, AbstractPipeline* pipeline) {
272
        // create canvas and painter for the pipeline and connect all together
273
        
274
        GLJobProc.registerContext(canvas);
275
276
        canvas->init();

277
        CampVisPainter* painter = new CampVisPainter(canvas, pipeline);
278
        canvas->setPainter(painter, false);
279
        pipeline->setCanvas(canvas);
280

281
282
283
        _visualizations.push_back(std::make_pair(pipeline, painter));
        _pipelines.push_back(pipeline);

284
        if (_initialized) {
285
            LGL_ERROR;
286
            pipeline->init();
287
            LGL_ERROR;
288
            painter->init();
289
            LGL_ERROR;
290
291
        }

292
        tgt::GlContextManager::getRef().releaseCurrentContext();
293
294
295
296
297
298
299
        _mainWindow->addVisualizationPipelineWidget(name, canvas);

        // enable pipeline and invalidate all processors
        pipeline->setEnabled(true);
        for (std::vector<AbstractProcessor*>::const_iterator it = pipeline->getProcessors().begin(); it != pipeline->getProcessors().end(); ++it) {
            (*it)->invalidate(AbstractProcessor::INVALID_RESULT);
        }
300
301
    }

302
303
304
305
306
307
    void CampVisApplication::registerDockWidget(Qt::DockWidgetArea area, QDockWidget* dock) {
        tgtAssert(dock != 0, "Dock widget must not be 0.");

        _mainWindow->addDockWidget(area, dock);
    }

308
309
310
311
312
    DataContainer* CampVisApplication::createAndAddDataContainer(const std::string& name) {
        DataContainer* dc = new DataContainer(name);
        _dataContainers.push_back(dc);
        s_DataContainersChanged();
        return dc;
313
314
315
    }


316
}