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 12.2 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
#include "application/campvispainter.h"
38
#include "application/gui/mainwindow.h"
39
#include "core/tools/job.h"
40
#include "core/tools/opengljobprocessor.h"
41
#include "core/tools/simplejobprocessor.h"
42
#include "core/tools/stringutils.h"
43
#include "core/tools/quadrenderer.h"
44
#include "core/pipeline/abstractpipeline.h"
45
#include "core/pipeline/visualizationprocessor.h"
46
#include "modules/pipelinefactory.h"
47

schultezub's avatar
schultezub committed
48
namespace campvis {
49

50
    const std::string CampVisApplication::loggerCat_ = "CAMPVis.application.CampVisApplication";
51

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

63
64
        _mainWindow = new MainWindow(this);
        tgt::QtContextManager::init();
65
66

        OpenGLJobProcessor::init();
67
        SimpleJobProcessor::init();
68
69
    }

70
71
    CampVisApplication::~CampVisApplication() {
        tgtAssert(_initialized == false, "Destructing initialized CampVisApplication, deinitialize first!");
72
73

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

85
86
    void CampVisApplication::init() {
        tgtAssert(_initialized == false, "Tried to initialize CampVisApplication twice.");
87

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

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

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

106
        tgt::GLContextScopedLock lock(_localContext);
107

108
        tgt::initGL(featureset);
109
        ShdrMgr.setDefaultGlslVersion("330");
110
111
        LGL_ERROR;

112
        // ensure matching OpenGL specs
113
        if (GpuCaps.getGlVersion() < tgt::GpuCapabilities::GlVersion::TGT_GL_VERSION_3_3) {
114
            LERROR("Your system does not support OpenGL 3.3, which is mandatory. CAMPVis will probably not work as intended.");
115
        }
116
        if (GpuCaps.getShaderVersion() < tgt::GpuCapabilities::GlVersion::SHADER_VERSION_330) {
117
118
119
120
            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.");
121
122
        }

123
        QuadRenderer::init();
124
        
125
126
        if (_argc > 0) {
            // ugly hack
schultezub's avatar
schultezub committed
127
            std::string basePath(_argv[0]);
128
129
130
131
132
            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
133
134
135
            ShdrMgr.addPath(basePath);
            ShdrMgr.addPath(basePath + "/core/glsl");

136
137
138
139
140
141
#ifdef CAMPVIS_SOURCE_DIR
            {
                std::string sourcePath = CAMPVIS_SOURCE_DIR;
                ShdrMgr.addPath(sourcePath);
                ShdrMgr.addPath(sourcePath + "/core/glsl");
            }
schultezub's avatar
schultezub committed
142
#endif
143
144
        }

145
146
        _mainWindow->init();

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

        // Now init painters:
153
        for (std::vector< std::pair<AbstractPipeline*, CampVisPainter*> >::iterator it = _visualizations.begin(); it != _visualizations.end(); ++it) {
154
155
156
            it->second->init();
        }

157
        GLJobProc.start();
158
        GLJobProc.registerContext(_localContext);
159
160
161
        _initialized = true;
    }

162
163
    void CampVisApplication::deinit() {
        tgtAssert(_initialized, "Tried to deinitialize uninitialized CampVisApplication.");
164

165
166
        GLJobProc.stop();

167
168
        {
            // Deinit everything OpenGL related using the local context.
169
            tgt::GLContextScopedLock lock(_localContext);
170

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

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

181
            _mainWindow->deinit();
182
183
            QuadRenderer::deinit();

184
185
            // deinit OpenGL and tgt
            tgt::deinitGL();
186
187
        }

188
        SimpleJobProcessor::deinit();
189
        OpenGLJobProcessor::deinit();
190
        PipelineFactory::deinit();
191

192
193
194
        tgt::QtContextManager::deinit();
        tgt::deinit();

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

198
199
200
        _initialized = false;
    }

201
202
    int CampVisApplication::run() {
        tgtAssert(_initialized, "Tried to run uninitialized CampVisApplication.");
203
204

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

207
208
        _mainWindow->show();

209
210
211
212
213
214
        // Start QApplication
        int toReturn = QApplication::exec();

        return toReturn;
    }

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

218
219
220
221
        // 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();
222
            {
223
224
225
                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);
226
227
228
                addPipelineImpl(canvas, name, pipeline);
            }
            GLJobProc.resume();
229
        }
230
        else {
231
232
            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.");
233
234
235
236
237
            addPipelineImpl(canvas, name, pipeline);
        }

        s_PipelinesChanged();
    }
238

239
    void CampVisApplication::addPipelineImpl(tgt::QtThreadedCanvas* canvas, const std::string& name, AbstractPipeline* pipeline) {
240
        // create canvas and painter for the pipeline and connect all together
241
        
242
        GLJobProc.registerContext(canvas);
243
244
        canvas->init();

245
        CampVisPainter* painter = new CampVisPainter(canvas, pipeline);
246
        canvas->setPainter(painter, false);
247
        pipeline->setCanvas(canvas);
248

249
250
251
        _visualizations.push_back(std::make_pair(pipeline, painter));
        _pipelines.push_back(pipeline);

252
        if (_initialized) {
253
            LGL_ERROR;
254
            pipeline->init();
255
            LGL_ERROR;
256
            painter->init();
257
            LGL_ERROR;
258
259
        }

260
        tgt::GlContextManager::getRef().releaseCurrentContext();
261
262
263
264
265
266
267
        _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);
        }
268
269
    }

270
271
272
273
274
275
    void CampVisApplication::registerDockWidget(Qt::DockWidgetArea area, QDockWidget* dock) {
        tgtAssert(dock != 0, "Dock widget must not be 0.");

        _mainWindow->addDockWidget(area, dock);
    }

276
277
278
279
280
    DataContainer* CampVisApplication::createAndAddDataContainer(const std::string& name) {
        DataContainer* dc = new DataContainer(name);
        _dataContainers.push_back(dc);
        s_DataContainersChanged();
        return dc;
281
282
    }

283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
    void CampVisApplication::rebuildAllShadersFromFiles() {
        // rebuilding all shaders has to be done from OpenGL context, use the local one.
        GLJobProc.enqueueJob(_localContext, makeJobOnHeap(this, &CampVisApplication::triggerShaderRebuild), OpenGLJobProcessor::SerialJob);
    }

    void CampVisApplication::triggerShaderRebuild() {

        if (! ShdrMgr.rebuildAllShadersFromFile()) {
            LERROR("Could not rebuild all shaders from file.");
            return;
        }

        for (std::vector<AbstractPipeline*>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
            for (std::vector<AbstractProcessor*>::const_iterator pit = (*it)->getProcessors().begin(); pit != (*it)->getProcessors().end(); ++pit) {
                if (VisualizationProcessor* tester = dynamic_cast<VisualizationProcessor*>(*pit)) {
                	tester->invalidate(AbstractProcessor::INVALID_RESULT);
                }
            }
        }
    }

304

305
}